Friday, June 17, 2016

Tutorial on Serialization in Java - Part1

What is serialization and how its performed?

Serialization is a mechanism through which we can save the state of an object by converting the object into a byte stream.

Serialized object (byte stream) can be transferred over network, persisted or saved into file/database.
We can deserialize the Serialized object (byte stream) and gets back the original object.

Let’s try to write a Java' program to serialize an object.

Let’s create a package ‘Serialization’ and create a class ‘TestObject’ for creating an object to be serialized.

TestObject.java

package Serialization;

class TestObject {
       int number;
       String name;
       TestObject(int i, String s) {
              number = i;
              name = s;
       }
}

Now, Let’s create a class SerializeUtility which has methods for serializing and deserializing the given object, in the same package ‘Serialization’.

SerializeUtility.java

package Serialization;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
class SerializeUtility {
      
       public void serialize(Object obj) {
              // TODO: implement serialize logic
       }
      
       public Object deSerialize() {
              // TODO: implement deserialize logic
              return null;
       }     
}

Now, let’s try to define the methods serialize() and deserialize() of class SerializeUtility.

To define serialize() method:

As we know,  Serialization is a mechanism through which we can save the state of an object by converting the object into a byte stream. So first we need to convert the object into byte stream. After that lets save the converted bytestream into some file. To achieve this, we need to

1. Create an object of FileOutputStream class and pass the file location where we want to store the object byte stream.
FileOutputStream fos = new FileOutputStream("testSerialization.txt");

2. Create an object of ObjectOutputStream object and send the reference of FileOutPutStream object as parameter to ObjectOutputStream constructor.
ObjectOutputStream oos = new ObjectOutputStream( fos );

3. Pass the object to be serialized to the method writeObject() of ObjectOutputStream.
oos.writeObject ( obj );

This method writeObject() actually the one which starts the serialization mechanism and the object is flattened (in this case to a file). We can close the streams at the end of the method and add expected exception catch blocks. You can take a look at the complete definition for serialize() below.

public void serialize (Object obj) {
              FileOutputStream fos = null;
              ObjectOutputStream oos = null;
              try {
                     fos = new FileOutputStream("testSerialization.txt");
                     oos = new ObjectOutputStream(fos);
                     oos.writeObject(obj);
              } catch (FileNotFoundException e) {
                     e.printStackTrace();
              } catch (IOException e) {
                     e.printStackTrace();
              }
              finally {
                     try {
                           oos.close();
                           fos.close();
                     } catch (IOException e) {
                           e.printStackTrace();
                     }                   
              }
       }

To define  deserialize() method:

As we know,  deserialization is a process of getting back the original object from the saved object stream content. . To achieve this, we need to

1. Create an object of FileInputStream class and pass the file location where we stored the object byte stream file.
FileInputStream fis = new FileInputStream("testSerialization.txt");

2. Create an object of ObjectInputStream object and send the reference of FileInPutStream object as parameter to ObjectInputStream constructor.
ObjectInputStream ois = new ObjectInputStream( fis );

3. Return the object from the method readObject() of ObjectInputStream.
ois.readObject ();

This method readObject() reads the raw bytes that we previously persisted and creates a live object that is an exact replica of the original. Because readObject() can read any serializable object, a cast to the correct type is required.  The class file must be accessible from the system in which the restoration occurs. In other words, the object's class file and methods are not saved, only the object's state is saved.

We can close the streams at the end of the method and add expected exception catch blocks. You can take a look at the complete definition for deserialize() below:

public Object deSerialize() {
              FileInputStream fis = null;
              ObjectInputStream ois = null;
              try {
                     fis = new FileInputStream("testSerialization.txt");
                     ois = new ObjectInputStream(fis);
                     return ois.readObject();
              } catch (FileNotFoundException e) {
                     e.printStackTrace();
              } catch (IOException e) {
                     e.printStackTrace();
              } catch (ClassNotFoundException e) {
                     e.printStackTrace();
              }
              finally {
                     try {
                           ois.close();
                           fis.close();
                     } catch (IOException e) {
                           e.printStackTrace();
                     }
              }
              return null;
       }

You can take a look at the complete class definition for ‘SerializeUtility’ below:

SerializeUtility.java

package Serialization;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

class SerializeUtility {
      
       public void serialize(Object obj) {
              FileOutputStream fos = null;
              ObjectOutputStream oos = null;
              try {
                     fos = new FileOutputStream("testSerialization.txt");
                     oos = new ObjectOutputStream(fos);
                     oos.writeObject(obj);
              } catch (FileNotFoundException e) {
                     e.printStackTrace();
              } catch (IOException e) {
                     e.printStackTrace();
              }
              finally {
                     try {
                           oos.close();
                           fos.close();
                     } catch (IOException e) {
                           e.printStackTrace();
                     }
              }
       }
      
       public Object deSerialize() {
              FileInputStream fis = null;
              ObjectInputStream ois = null;
              try {
                     fis = new FileInputStream("testSerialization.txt");
                     ois = new ObjectInputStream(fis);
                     return ois.readObject();
              } catch (FileNotFoundException e) {
                     e.printStackTrace();
              } catch (IOException e) {
                     e.printStackTrace();
              } catch (ClassNotFoundException e) {
                     e.printStackTrace();
              }
              finally {
                     try {
                           ois.close();
                           fis.close();
                     } catch (IOException e) {
                           e.printStackTrace();
                     }
              }
              return null;
       }      
}

Now, lets serialize and deserialize the TestObject’s object with the SerializeUtility’s methods serialize() and deserialize(). For that we need to create a class SerializationTest in the same package ‘Serialization’ and have an TestObject instance and call serialize() of SerializeUtility in the main method as shown below, similar can be done for deserialize.

SerializationTest.java

package Serialization;

public class SerializationTest {
       public static void main(String[] args) {
              TestObject tObj1 = new TestObject(10, "TestSerialization");
              SerializeUtility utility = new SerializeUtility();
             
              // serialization
              utility.serialize(tObj1);
              // deserialization
              TestObject tObj2 = (TestObject)utility.deSerialize();
             
              System.out.println("Number: " + tObj2.number);
              System.out.println("Name: " + tObj2.name);
       }
}

Don’t try to run this class ‘SerializationTest’. If you do so, you will get java.io.NotSerializableException: TestObject. As JVM sees that the object of ‘TestObject’ class is not eligible for serialization and hence throws the exception. So, to make any instance of the class ‘TestObject’ eligible for serialize, ‘TestObject’ class needs to implement  Serializable interface as shown below.

TestObject.java

package Serialization;

import java.io.Serializable;

public class TestObject implements Serializable {
       int number;
       String name;
       TestObject(int i, String s) {
              number = i;
              name = s;
       }
}

 Serializable interface is a marker interface means contains no fields or methods within it and is used to indicate to JVM, that any instance of this class is ready to be serialized.

If you compile all classes which we created so far (SerializationTest.java, SerializationUtility.java and TestObject.java) and run SerializationTest.java (which contains main() method) , you will get the following output:

Number: 10

Name: TestSerialization

1 comment: