Saturday 25 April 2015

What is Serialization in Java? Where we use Serialization?

       Java Serialization allows us to convert an Object to byte stream that we can send over the network or save it as file or store in DB for later usage.
       Deserialization is the process of converting Object stream to actual Java Object  to be used in our program.

Serialization In Java
       Image: Serialization & Deserialization Process

      If you want a class object to be serializable, all you need to do it implement the java.io.Serializable interface.  Serializable is a marker interface and has no fields or methods to implement.
      Serialization process is implemented by ObjectInputStream and ObjectOutputStream, so all we need is a wrapper over them to either save it to file or send it over the network. Let’s see a simple Serialization example.

java.io.Serializable Interface:

    package com.adnblog;
    import java.io.Serializable;

    public class Student implements Serializable {

            private static final long serialVersionUID = 6470090944414208496L;
            private String name;
            private int id;
            transient private String address;
          
            @Override
            public String toString(){
                     return     "Student{name="+name+",id="+id+",address="+address+"}";
            }

            //getter and setter methods
            public String getName() {
                     return name;
            }
            public void setName(String name) {
                    this.name = name;
            }

            public int getId() {
                    return id;
            }
            public void setId(int id) {
                    this.id = id;
            }

            public String getAddress() {
                   return address;
            }
            public void setAddress(String address) {
                    this.address = address;
            }
     } 

  Notice that for a class to be serialized successfully, two conditions must be met:
1)The class must implement the java.io.Serializable interface.
2)All of the fields in the class must be serializable. If a field is not serializable, it must be marked as transient. In the above Student class address is non-serializable field.

       Now, once a class is serializable, we can write the object to any OutputStream, such as to disk or a socket connection. To achieve this, we must first create an instance of java.io.ObjectOutputStream, and pass the constructor an existing OutputStream instance.
 
     package com.adnblog;

     import java.io.FileOutputStream;
     import java.io.ObjectOutputStream;

     public class SerializeObject {
           public static void main(String[] args) {
                  String filename = "Serialize.ser";    //give the file name with file name
                  Student st = new Student();
                  st.setName("Anil");
                  st.setId(24);
                  st.setAddress("A/P-Sonyal,Tal-Jath,Dist-Sangli");

                  // save the object to file
                  FileOutputStream fos = null;
                  ObjectOutputStream out = null;
                  try {
                       fos = new FileOutputStream(filename);
                       out = new ObjectOutputStream(fos);
                       out.writeObject(st);
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  } finally {
                       if(out != null) {
                             out.close();
                       }
                  }
            }
     }

Deserialization:--

       Deserialization is the process of converting Object stream to actual Java Object  to be used in our program. Below is code for deserialization of java objects, here we just need to get an FileInputStream object from the file that contains object's bytes and pass this to ObjectInputStream's object's constructor. Method readObject() returns an object whose bytes are being read from the file.

          package com.adnblog;

          import java.io.FileInputStream;
          import java.io.ObjectInputStream;

          public class DeserializeObject {
                   public static void main(String[] args) {
                            String filename = "Serialize.ser";   
                            Student st = null;
                               // read the object from file
                            FileInputStream fis = null;
                            ObjectInputStream ois = null;
                            try {
                                   fis = new FileInputStream(filename);
                                   ois = new ObjectInputStream(fis);
                                   st = (Student) ois.readObject();
                            } catch (Exception ex) {
                                          ex.printStackTrace();
                            }
                            finally {
                                       if(ois != null) {
                                             ois.close();

                                      }

                            }
                            System.out.println(st);
                   }
           }

Uses Of  Serialization:-
    1. Banking example: When the account holder tries to withdraw money from the server through ATM, the account holder information along with the withdrawl details will be serialized (marshalled/flattened to bytes) and sent to server where the details are deserialized (unmarshalled/rebuilt the bytes)and used to perform operations. This will reduce the network calls as we are serializing the whole object and sending to server and further request for information from client is not needed by the server.

    2. Stock example: Lets say an user wants the stock updates immediately when he request for it. To achieve this, everytime we have an update, we can serialize it and save it in a file. When user requests the information, deserialize it from file and provide the information. This way we dont need to make the user wait for the information until we hit the database, perform computations and get the result.

Here are some uses of serialization

1. Convert java object into byte stream and then it can be saved in database for persistence.
2. If two JVM want to communicate, then object serialization is one of the approaches.
3. Send the java object in network as byte stream by serialization and at the other end deserialize to get  same object in same state.
4. Cache the object by serialization instead of keeping it in memory.

Serialization and Deserialization Related Questions:

1) What is a serialVersionUID and why should  use it?

          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;

2) Do we need to implement any method of Serializable interface to make an object serializable?
 No. Serializable is a Marker Interface. It does not have any methods.

3) How to make the field as Non Serializable?
         Sometimes you don't want to serialize/store all the fields in the object. Say some fields you want to hide to preserve the privacy or some fields you may want to read only from master data, then you don't serialize them. To do this, you just need to declare a field as transient field.

        transient private String address;

       Also the static fields are not serialized. Actually there is no point in serializing static fields as static fields do not represent object state but represent class state and it can be modified by any other object. Lets assume that you have serialized a static field and its value and before deserialization of the object, the static field value is changed by some other object. Now the static field value that is serialized/stored is no more valid. Hence it make no point in serializing the static field.

Note :-- The static and transient fields can not be serialized.