July 01, 2016

Serialization of Singleton class..

Serialization is a process by which you can save or transfer the state of an object by converting it to a byte stream. During deserialization, the object is re-created.

And with Singleton design pattern, we control object instantiation. With this creational design pattern we make sure that only single object gets created.

ALSO READ: Serialization Interview Questions and Answers for Experienced Developers

However,  when we serialize a singleton class and invoke deserialization multiple times we can end up with multiple objects of the singleton class. Even though constructor in singleton class is declared as private, deserialization process gets hold of the private constructor while recreating the object from the serialized data store.

ALSO READ: Design Patterns and Singleton class..

How do you prevent for creating another instance of Singleton during serialization?
We can achieve this by using readResolve() method.

The readResolve() method is called when ObjectInputStream read an object from the stream and is preparing to return it to the caller.

ObjectInputStream checks whether the class of the object defines the readResolve() or not. If the method is defined, the readResolve() is called to allow the object in the stream to designate the object to be returned.

The object returned should be of a type that is compatible with all uses. If it is not compatible, a ClassCastException will be thrown when the type mismatch is discovered.

Let was take an example:

Create a singleton class
package com.khs.singletontest;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class EmployeeSingleton implements Serializable
{
    private static EmployeeSingleton employee;
   
    /*private constructor*/
    private EmployeeSingleton(){}
   
    public static EmployeeSingleton getEmployeeSingletonInstance()
    {
        if(employee==null)
            employee=new EmployeeSingleton();
        return employee;
    }
}


Create a class, which serialize and then de-serialize EmployeeSingleton object

package com.khs.singletontest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeEmployee {
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException{
        EmployeeSingleton employee = EmployeeSingleton.getEmployeeSingletonInstance();

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("connFactory.ser"));
        oos.writeObject(employee);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("connFactory.ser"));
        EmployeeSingleton factory1 = (EmployeeSingleton) ois.readObject();
        ois.close();

        ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream("connFactory.ser"));
        EmployeeSingleton factory2 = (EmployeeSingleton) ois2.readObject();
        ois2.close();

        System.out.println("Instance reference of factory1 : "+ factory1.getEmployeeSingletonInstance());
        System.out.println("Instance reference of factory2 : "+ factory2.getEmployeeSingletonInstance());
        System.out.println("Instance reference of factory1 : "+ factory1);
        System.out.println("Instance reference of factory2 : "+ factory2);
    }
}


Output of SerializeEmployee is :
Instance reference of factory1 : com.khs.singletontest.EmployeeSingleton@de6ced
Instance reference of factory2 : com.khs.singletontest.EmployeeSingleton@de6ced
Instance reference of factory1 : com.khs.singletontest.EmployeeSingleton@c17164
Instance reference of factory2 : com.khs.singletontest.EmployeeSingleton@1fb8ee3


Now add readResolve() method in EmployeeSingleton :

private Object readResolve() throws ObjectStreamException {
        return employee;
    }


Now check the output of SerializeEmployee:
Instance reference of factory1 : com.khs.singletontest.EmployeeSingleton@de6ced
Instance reference of factory2 : com.khs.singletontest.EmployeeSingleton@de6ced
Instance reference of factory1 : com.khs.singletontest.EmployeeSingleton@de6ced
Instance reference of factory2 : com.khs.singletontest.EmployeeSingleton@de6ced


-K Himaanshu Shuklaa.. 

No comments:

Post a Comment

RSSChomp Blog Directory