Tuesday, April 25, 2017

Java Serialization - Part II

We have already discussed the basics of Java Serialization in part I of this article. 

Now let's discuss it deeply and how it works.

First let's start with the serialversionuid.

The serialVersionUID is used as a version control in a Serializable class. 

If you do not explicitly declare a serialVersionUID,  JVM will do it for you automatically, based on various properties of the Serializable class. 

Java's Algorithm of Calculating serialversionuid (Read more details here)
  1. The class name.
  2. The class modifiers written as a 32-bit integer.
  3. The name of each interface sorted by name.
  4. For each field of the class sorted by field name (except private static and private transient fields:
    1. The name of the field.
    2. The modifiers of the field written as a 32-bit integer.
    3. The descriptor of the field.
  5. If a class initializer exists, write out the following:
    1. The name of the method, <clinit>.
    2. The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer.
    3. The descriptor of the method, ()V.
  6. For each non-private constructor sorted by method name and signature:
    1. The name of the method, <init>.
    2. The modifiers of the method written as a 32-bit integer.
    3. The descriptor of the method.
  7. For each non-private method sorted by method name and signature:
    1. The name of the method.
    2. The modifiers of the method written as a 32-bit integer.
    3. The descriptor of the method.
  8. The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and produces five 32-bit values sha[0..4].
  9. The hash value is assembled from the first and second 32-bit values of the SHA-1 message digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named sha, the hash value would be computed as follows:
      long hash = ((sha[0] >>> 24) & 0xFF) |
           ((sha[0] >>> 16) & 0xFF) << 8 |
           ((sha[0] >>> 8) & 0xFF) << 16 |
           ((sha[0] >>> 0) & 0xFF) << 24 |
           ((sha[1] >>> 24) & 0xFF) << 32 |
           ((sha[1] >>> 16) & 0xFF) << 40 |
           ((sha[1] >>> 8) & 0xFF) << 48 |
           ((sha[1] >>> 0) & 0xFF) << 56;

Java's serialization algorithm

The algorithm to serialize an object is described as below:
  • It writes out the metadata of the class associated with an instance.
  • It recursively writes out the description of the superclass until it finds java.lang.object.
  • Once it finishes writing the metadata information, it then starts with the actual data associated with the instance. But this time, it starts from the topmost superclass.
  • It recursively writes the data associated with the instance, starting from the least superclass to the most-derived class.

Things To Keep In Mind:

1. Static fields in a class cannot be serialized. 

public class A implements Serializable{
     String s;
     static String staticString = "I won't be serializable";
}

2. If the serialversionuid is different in the read class it will throw a Class cast exception.

3. If a class implements serializable then all its sub classes will also be serializable.

public class A implements Serializable {....};

public class B extends A{...} //also Serializable


4. If a class has a reference of another class, all the references must be Serializable otherwise serialization process will not be performed. In such case, NotSerializableException is thrown at runtime.

Eg:

    public class B{
         String s,
         A a; // class A needs to be serializable i.e. it must implement Serializable
    }

Friday, April 21, 2017

Java Serialization and Deserialization - Part I

Serialization:

Serialization is the process of serializing the state of an object is represented and stored in the form of a sequence of bytes. This can be stored in a file. The process to read the state of the object from the file and restoring it is called deserialization.


What is the need of Serialization?

In modern day architecture, there is always a need to store object state and then retrieve it. For example in Hibernate, to store a object we should make the class Serializable. What it does, is that once the object state is saved in the form of bytes it can be transferred to another system which can then read from the state and retrieve the class. The object state can come from a database or a different jvm or from a separate component. With the help of Serialization we can retrieve the Object state.  

Code Example and explanation:

First let's have a look at the Item Class:


public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }

}


In the above code it can be seen that Item class implements Serializable

This is the interface that enables a class to be serializable. 

Now we can see a variable called serialVersionUID is initialized to Long variable. This number is calculated by the compiler based on the state of the class and the class attributes. This is the number that will help the jvm identify the state of an object when it reads the state of the object from file. 

For that we can have a look at the official Oracle Documentation:

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.

For more examples on the above look at my article on serialVersionUID.

If you have noticed there is another keyword we have used which is transient.

If a field is not serializable, it must be marked transient. Here we marked the itemCostPrice as transient and don't want it to be written in a file

Now let's have a look on how to write the state of an object in the file and then read it from there.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    } 

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

In the above we can see an example of serialization and deserialization of an object. 

For that we used two classes. For serializing the object we have used ObjectOutputStream. We have used the method writeObject to write the object in the file. 

For Deserializing we have used ObjectInputStream which reads from the object from the file. It uses readObject to read the object data from the file. 

The output of the above code would be like:

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]


Notice that itemCostPrice from deserialized object is null as it was not written.

Friday, April 14, 2017

Stateless Session Bean

In this article we are going to discuss about Stateless Session Beans.

First let's start with the remote bean interface:

package com.baeldung.ejb.stateless.beans;

import java.util.List;

import javax.ejb.Remote;

@Remote
public interface ItemStatelessRemote {

    void addItem(String itemName);

    List<String> getItemList();
}

Now let's have a look at the implementation of the above bean:

package com.baeldung.ejb.stateless.beans;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;

@Stateless(name = "ItemStatelessRemote")
public class ItemStateless implements ItemStatelessRemote {

    private List<String> itemList;

    public ItemStateless() {
        itemList = new ArrayList<String>();
    }

    @Override
    public void addItem(String itemName) {
        itemList.add(itemName);
    }

    @Override
    public List<String> getItemList() {
        return itemList;
    }

}

Here we use @Stateless(name = "ItemStatelessRemote") to make the bean stateless.

Stateless beans retain the variables across multiple states, and hence the name.

Now let's have a look at the client:

package com.baeldung.ejb.session.client;

import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.baeldung.ejb.stateless.beans.ItemStatelessRemote;

public class EJBStatelessClient {

    public EJBStatelessClient() {
    }

    private Context context = null;

    public static void main(String[] arg) {
        EJBStatelessClient ejb = new EJBStatelessClient();
        System.out.println(ejb.getEJBRemoteMessage());

    }

    public Boolean getEJBRemoteMessage() {
        EJBStatelessClient main = new EJBStatelessClient();
        Boolean result = true;
        try {
            // 1. Obtaining Context
            main.createInitialContext();
            // 2. Generate JNDI Lookup name and caste
            ItemStatelessRemote itemStatelessOne = main.lookup();
            ItemStatelessRemote itemStatelessTwo = main.lookup();

            itemStatelessOne.addItem("Book");
            itemStatelessOne.addItem("Pen");
            itemStatelessOne.addItem("Pencil");
            itemStatelessOne.addItem("Eraser");

            result = itemStatelessOne.getItemList().equals(itemStatelessTwo.getItemList());

            return result;
        } catch (NamingException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                main.closeContext();
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }
    }

    public ItemStatelessRemote lookup() throws NamingException {

        // The app name is the EAR name of the deployed EJB without .ear suffix.
        // Since we haven't deployed the application as a .ear, the app name for
        // us will be an empty string
        final String appName = "";
        final String moduleName = "session-beans";
        final String distinctName = "";
        final String beanName = "ItemStatelessRemote";
        final String viewClassName = ItemStatelessRemote.class.getName();
        final String toLookup = String.format("ejb:%s/%s/%s/%s!%s", appName, moduleName, distinctName, beanName, viewClassName);

        return (ItemStatelessRemote) context.lookup(toLookup);
    }

    public void createInitialContext() throws NamingException {
        Properties prop = new Properties();
        prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
        prop.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
        prop.put(Context.SECURITY_PRINCIPAL, "testUser");
        prop.put(Context.SECURITY_CREDENTIALS, "admin1234!");
        prop.put("jboss.naming.client.ejb.context", false);

        context = new InitialContext(prop);
    }

    public void closeContext() throws NamingException {
        if (context != null) {
            context.close();
        }
    }

}

Thursday, April 13, 2017

Stateful Session Beans

In this article we are going to discuss how to setup session beans and how to use them.

The server we have used here is WildFly 10.1.0.

We have used maven cargo which will automatically download and run the server.

The whole project is available here.

You can download the code and then go through the explanations.

Let's start with Stateful beans Interface:

package com.baeldung.ejb.stateful.beans;

import java.util.List;

import javax.ejb.Remote;

@Remote
public interface ItemStatefulRemote {

    void addItem(String itemName);

    List<String> getItemList();

}

The ```@Remote``` signifies that the bean is remote.

After that we implement the class.

package com.baeldung.ejb.stateful.beans;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateful;

@Stateful(name = "ItemStatefulRemote")
public class ItemStateful implements ItemStatefulRemote {

    private List<String> itemList;

    public ItemStateful() {
        itemList = new ArrayList<String>();
    }

    @Override
    public void addItem(String itemName) {
        itemList.add(itemName);
    }

    @Override
    public List<String> getItemList() {
        return itemList;
    }

}


@Stateful denotes that the bean is stateful bean. Once we are done with the coding part we will discuss in details the difference between a stateful and stateless bean.

We are done with the implementation of the beans. 

Now let's implement the client which will access these beans:

package com.baeldung.ejb.session.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.baeldung.ejb.stateful.beans.ItemStatefulRemote;

public class EJBStatefulClient {

 public EJBStatefulClient() {
 }

 private Context context = null;

 public Boolean getEJBRemoteMessage() {
  EJBStatefulClient ejb = new EJBStatefulClient();
  Boolean result = true;
  try {
   // 1. Obtaining Context
   ejb.createInitialContext();
   // 2. Generate JNDI Lookup name and caste
   ItemStatefulRemote itemStatefulOne = ejb.lookup();
   ItemStatefulRemote itemStatefulTwo = ejb.lookup();

   itemStatefulOne.addItem("Book");
   itemStatefulOne.addItem("Pen");
   itemStatefulOne.addItem("Copy");
   itemStatefulOne.addItem("Pencil");

   result = itemStatefulOne.getItemList().equals(itemStatefulTwo.getItemList());

   return result;
  } catch (NamingException e) {
   e.printStackTrace();
   return false;
  } finally {
   try {
    ejb.closeContext();
   } catch (NamingException e) {
    e.printStackTrace();

   }
  }
 }

 public ItemStatefulRemote lookup() throws NamingException {

  // The app name is the EAR name of the deployed EJB without .ear suffix.
  // Since we haven't deployed the application as a .ear, the app name for
  // us will be an empty string
  final String appName = "";
  final String moduleName = "session-beans";
  final String distinctName = "";
  final String beanName = "ItemStatefulRemote";
  final String viewClassName = ItemStatefulRemote.class.getName() + "?stateful";
  final String toLookup = String.format("ejb:%s/%s/%s/%s!%s", appName, moduleName, distinctName, beanName,
    viewClassName);
  return (ItemStatefulRemote) context.lookup(toLookup);
 }

 public void createInitialContext() throws NamingException {
  Properties prop = new Properties();
  prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
  prop.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
  prop.put(Context.SECURITY_PRINCIPAL, "testUser");
  prop.put(Context.SECURITY_CREDENTIALS, "admin1234!");
  prop.put("jboss.naming.client.ejb.context", false);

  context = new InitialContext(prop);
 }

 public void closeContext() throws NamingException {
  if (context != null) {
   context.close();
  }
 }

This is the most important part of the ejb.

The client first uses the jndi notation to connect to the bean and after that it tries to add an item and look it up.

Since this is a stateful bean, it won't retain variables across states. 

We can design some tests to test this behavior:

package com.baeldung.ejb.session.client.test;

import static org.junit.Assert.*;

import org.junit.Test;

import com.baeldung.ejb.session.client.EJBStatefulClient;

public class EJBStatefulClientTest {

 @Test
 public void EJBClientTest() {
  EJBStatefulClient ejbStatefulClient = new EJBStatefulClient();
  assertFalse(ejbStatefulClient.getEJBRemoteMessage());
 }

}

For the entire application, look at my GitHub code. I have a detailed page on how to run the examples.

If you have any questions feel free to email me at pritambanerjee999@gmail.com