Wednesday 6 January 2016

Java Serialization - Example with IS-A and HAS-A relationship

Object Serialization
Object Serialization in Java is a process used to convert Object into a
binary format which can be persisted into disk or database or sent over network to
any other running Java virtual machine. Serialization
is very important feature provided by java api.
There are many other java technologies (JMS,EJB,RMI) uses serialization by default .
Making instances of your classes serializable is one step process. You just need add the implements Serializable clause to your class declaration
You need not  write any methods to implements serialization of your object. The serialization of instances of the class are handled implicitly by the defaultWriteObject method of ObjectOutputStream. This method automatically writes out everything required to reconstruct an instance of the class.
defaultWriteObject() is responsible for serializing below entity of the class object.
Values of all non-transient and non-static members, 
members reference (instance variable that refer to other object  ) .
Class signature
In this post , I am going to cover various scenario of the java serialization.  
Java serialization in IS-A relationship Suerclass is serialized but subclass is not serialized Superclass is not serialized but subclass is serialized Both Superclass and Subclass is serialized Both superclass and subclass is not serialized Java serialization in Has-A relationship Java object containing non serialized object reference. Java Object containing serializable object reference. Non Serializable java objects containing serializable Object reference.
Superclass is serialized but subclass is not serialized
Rule : 1
If parent class is implementing Serializable interface than all its child becomes serializable automatically. So no need to explicitly implement serializable interface in sub class. Below is the example to understand this scenario. Let us create two java class Account and sub class SavingAccount.
1:  import java.io.Serializable;  
2:  public class Account implements Serializable{  
3:       private String name;  
4:       private int accountId;  
5:       private String accountType;  
6:       public Account(){  
7:       }  
8:       public Account(String name, int accountId, String accountType) {  
9:            //super();  
10:            this.name = name;  
11:            this.accountId = accountId;  
12:            this.accountType = accountType;  
13:       }  
14:       public String getName() {  
15:            return name;  
16:       }  
17:       public void setName(String name) {  
18:            this.name = name;  
19:       }  
20:       public int getAccountId() {  
21:            return accountId;  
22:       }  
23:       public void setAccountId(int accountId) {  
24:            this.accountId = accountId;  
25:       }  
26:       public String getAccountType() {  
27:            return accountType;  
28:       }  
29:       public void setAccountType(String accountType) {  
30:            this.accountType = accountType;  
31:       }  
32:  }  








1:       public class SavingAccount extends Account{  
2:       private int id;  
3:       private int amount;  
4:       private static final long serialVersionUID = 1L;   
5:       public SavingAccount(String name,int accountId,String accountType,int id,int amount){  
6:            super(name,accountId,accountType);  
7:            this.id = id;  
8:            this.amount = amount;  
9:       }  
10:       public int getId() {  
11:            return id;  
12:       }  
13:       public void setId(int id) {  
14:            this.id = id;  
15:       }  
16:       public int getAmount() {  
17:            return amount;  
18:       }  
19:       public void setAmount(int amount) {  
20:            this.amount = amount;  
21:       }  
22:  }  




We are done now. Let us serialize and de-serialize this class. SerializationISARelationTest.java Run This code.



1:  import java.io.FileOutputStream;  
2:  import java.io.IOException;  
3:  import java.io.ObjectOutputStream;  
4:  public class SerializationISARelationTest {  
5:       /**  
6:        * @param args  
7:        */  
8:       public static void main(String[] args) {  
9:            // TODO Auto-generated method stub  
10:             //Account account=new Account("Saving",100,"SalaryAccount");  
11:             SavingAccount sAccount=new SavingAccount("Saving",100,"SalaryAccount",123456,5000);  
12:             try  
13:          {  
14:            FileOutputStream fileOut =  
15:            new FileOutputStream("/account.ser");  
16:            ObjectOutputStream out = new ObjectOutputStream(fileOut);  
17:            out.writeObject(sAccount);  
18:            out.close();  
19:            fileOut.close();  
20:            System.out.printf("Serialized data is saved in the file :: /account.ser");  
21:          }catch(IOException exp)  
22:          {  
23:            exp.printStackTrace();  
24:          }  
25:       }  
26:  }  





Run This code.

1:  import java.io.FileInputStream;  
2:  import java.io.IOException;  
3:  import java.io.ObjectInputStream;  
4:  public class DeserializeISARelation {  
5:       /**  
6:        * @param args  
7:        */  
8:       public static void main(String[] args) {  
9:            // TODO Auto-generated method stub  
10:            Account account=null;  
11:            SavingAccount saveAccount=null;  
12:            try  
13:          {  
14:            FileInputStream fileIn = new FileInputStream("/account.ser");  
15:            ObjectInputStream in = new ObjectInputStream(fileIn);  
16:            saveAccount = (SavingAccount) in.readObject();  
17:            in.close();  
18:            fileIn.close();  
19:          }catch(IOException exp)  
20:          {  
21:            exp.printStackTrace();  
22:            return;  
23:          }catch(ClassNotFoundException c)  
24:          {  
25:            System.out.println("Employee class not found");  
26:            c.printStackTrace();  
27:            return;  
28:          }  
29:             System.out.println("**************************************************************************");  
30:          System.out.println("Deserialized Account details..");  
31:          System.out.println("Account Name: " + saveAccount.getName());  
32:          System.out.println("account Id: " + saveAccount.getAccountId());  
33:          System.out.println("Account type: " + saveAccount.getAccountType());  
34:          System.out.println("**************************************************************************");  
35:          System.out.println(" Saving Account Deserialization : ");  
36:          System.out.println("saving Account ID: " + saveAccount.getId());  
37:          System.out.println("Amount: " + saveAccount.getAmount());  
38:          System.out.println("**************************************************************************");  
39:       }  
40:  }  
Output :
************************************************************************** Deserialized Account details..
Account Name: Saving account
Id: 100
Account type: SalaryAccount
**************************************************************************
Saving Account Deserialization :
 saving Account ID: 123456
 Amount: 5000

**************************************************************************

Superclass is not serialized but subclass is serialized

. Rule :1 If superclass is not serializable and subclass object is serialized then state of the member variable of subclass will be saved but not the superclass.



1:  import java.io.Serializable;  
2:  public class Account {  
3:       private String name;  
4:       private int accountId;  
5:       private String accountType;  
6:       public Account(){  
7:       }  
8:       public Account(String name, int accountId, String accountType) {  
9:            //super();  
10:            this.name = name;  
11:            this.accountId = accountId;  
12:            this.accountType = accountType;  
13:       }  
14:       public String getName() {  
15:            return name;  
16:       }  
17:       public void setName(String name) {  
18:            this.name = name;  
19:       }  
20:       public int getAccountId() {  
21:            return accountId;  
22:       }  
23:       public void setAccountId(int accountId) {  
24:            this.accountId = accountId;  
25:       }  
26:       public String getAccountType() {  
27:            return accountType;  
28:       }  
29:       public void setAccountType(String accountType) {  
30:            this.accountType = accountType;  
31:       }  
32:  }  




1:  import java.io.IOException;  
2:  import java.io.NotSerializableException;  
3:  import java.io.ObjectInputStream;  
4:  import java.io.ObjectOutputStream;  
5:  import java.io.Serializable;  
6:  public class SavingAccount extends Account implements Serializable{  
7:       private int id;  
8:       private int amount;  
9:       private static final long serialVersionUID = 1L;   
10:       public SavingAccount(String name,int accountId,String accountType,int id,int amount){  
11:            super(name,accountId,accountType);  
12:            this.id = id;  
13:            this.amount = amount;  
14:       }  
15:       public int getId() {  
16:            return id;  
17:       }  
18:       public void setId(int id) {  
19:            this.id = id;  
20:       }  
21:       public int getAmount() {  
22:            return amount;  
23:       }  
24:       public void setAmount(int amount) {  
25:            this.amount = amount;  
26:       }  
27:  }  




1:  <pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;">1: import java.io.IOException;   
2:  2: import java.io.NotSerializableException;   
3:  3: import java.io.ObjectInputStream;   
4:  4: import java.io.ObjectOutputStream;   
5:  5: import java.io.Serializable;   
6:  6: public class SavingAccount extends Account implements Serializable{   
7:  7:    private int id;   
8:  8:    private int amount;   
9:  9:    private static final long serialVersionUID = 1L;    
10:  10:    public SavingAccount(String name,int accountId,String accountType,int id,int amount){   
11:  11:      super(name,accountId,accountType);   
12:  12:      this.id = id;   
13:  13:      this.amount = amount;   
14:  14:    }   
15:  15:    public int getId() {   
16:  16:      return id;   
17:  17:    }   
18:  18:    public void setId(int id) {   
19:  19:      this.id = id;   
20:  20:    }   
21:  21:    public int getAmount() {   
22:  22:      return amount;   
23:  23:    }   
24:  24:    public void setAmount(int amount) {   
25:  25:      this.amount = amount;   
26:  26:    }   
27:  27: }   
28:  </code></pre>  




1:  import java.io.FileInputStream;  
2:  import java.io.IOException;  
3:  import java.io.ObjectInputStream;  
4:  public class DeserializeISARelation {  
5:       /**  
6:        * @param args  
7:        */  
8:       public static void main(String[] args) {  
9:            // TODO Auto-generated method stub  
10:            Account account=null;  
11:            SavingAccount saveAccount=null;  
12:            try  
13:          {  
14:            FileInputStream fileIn = new FileInputStream("/account.ser");  
15:            ObjectInputStream in = new ObjectInputStream(fileIn);  
16:            saveAccount = (SavingAccount) in.readObject();  
17:            in.close();  
18:            fileIn.close();  
19:          }catch(IOException exp)  
20:          {  
21:            exp.printStackTrace();  
22:            return;  
23:          }catch(ClassNotFoundException c)  
24:          {  
25:            System.out.println("Employee class not found");  
26:            c.printStackTrace();  
27:            return;  
28:          }  
29:             System.out.println("**************************************************************************");  
30:          System.out.println("Deserialized Account details..");  
31:          System.out.println("Account Name: " + saveAccount.getName());  
32:          System.out.println("account Id: " + saveAccount.getAccountId());  
33:          System.out.println("Account type: " + saveAccount.getAccountType());  
34:          System.out.println("**************************************************************************");  
35:          System.out.println(" Saving Account Deserialization : ");  
36:          System.out.println("saving Account ID: " + saveAccount.getId());  
37:          System.out.println("Amount: " + saveAccount.getAmount());  
38:          System.out.println("**************************************************************************");  
39:       }  
40:  }  
Output of the member variable of superclass is default value. the value which was explicitly set before serialization is not reflected in superclass output .

Output :
**************************************************************************
Deserialized Account details..
Account Name: null
account Id: 0
Account type: null
**************************************************************************
 Saving Account Deserialization : 
saving Account ID: 123456
Amount: 5000
**************************************************************************
Both Superclass and Subclass is serialized
Rule 1

If both superclass and subclass is serialized then state of member variable of both the class will be saved.

Output :
**************************************************************************
Deserialized Account details.
Account Name: Saving
account Id: 100
Account type: SalaryAccount
**************************************************************************
 Saving Account Deserialization :
saving Account ID: 123456
Amount: 5000
**************************************************************************

Both Superclass and Subclass is not serialized

Not Serializable exception will be thrown as shown below:-

java.io.NotSerializableException: com.java.serialization.SavingAccount
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at com.java.serialization.SerializationISARelationTest.main(SerializationISARelationTest.java:23)

Some facts about Java serialization
Implicit caching

Default behavior for Java serialization is to serialize any unique object just once. When you resend objects when their values changed. Although the object had been sent again with new value,it still will have  its original value previously stored due to implicit caching to improve performance. 
The ObjectOutputStream caches instances that it sends over the. But in any case, you need to send latest value streams in-between calls if you plan on using it to (re)send the same object instance. Then use reset() method
public void reset() throws IOException
Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.

Versioning

Consequence of not specifying  serialVersionUID in your serialized class is that when you add or modify any field in class then already serialized class will not be able to recover because serialVersionUID generated for new class and for old serialized object will be different.
Java serialization process relies on correct serialVersionUID for recovering state of serialized object and throws java.io.InvalidClassException in case of erialVersionUID mismatch.
It is recommended that alway declare serialVersionUID

Static final long serialVersionUID = 1L; // 1L is just an example!

Some Quick important points about serialization:-


  1. When you serialize an object, the serialization mechanism works by chaining up the inheritance hierarchy, saving the sate of each Serializable super-class in turn. When serialization reaches the first non-serializable super-class, the serialization stops.
  2. If member variables of a serializable object reference to a non-serializable object, the code will compile but a Runtime Exception  NotSerializableException will be thrown.
  3.  Static fields (with static modifier) are Not serialized.
  4.  All primitive types are serializable.
  5.  Transient fields (with transient modifier) are NOT serialized, (i.e., not saved or restored).A class that implements Serializable must mark -transient fields of classes that do not support serialization (e.g., a file stream).
  6. An object is serializable only if its class or its super-class implements the Serializable (or Externalizable) interface.
  7.  An object is serializable (itself implements the Serializable interface) even if its superclass is not. However, the first superclass in the hierarchy of the serializable class, that does not implements Serializable interface, MUST have a no-arg constructor. If this is violated, readObject() will produce a java.io.InvalidClassException in runtime.
  8.  The no-arg contructor of every non-serializable superclass will run when an object is deserialized. However, the deserialized objects? constructor does not run when it is deserialized.
  9.  The class must be visible at the point of serialization.



Next Post we will see serialization with HAS-A relationship.


Happy Reading..




6 comments:

  1. How to serialize HAS-a relationship?

    For eg.

    Class A is serialize Class B is not serialize. where Class B is in other package we can modify its definition.
    and we are creating Class B object in class A then it will throw run time exception.
    But Is there any way to serialize Class B object?

    ReplyDelete
    Replies
    1. You can't serialize this Class B. Better make it transient and serialize your Class A.

      Delete
  2. I really enjoy simply reading all of your weblogs. Simply wanted to inform you that you have people like me who appreciate your work. Definitely a great post I would like to read this
    Data Science training in Chennai
    Data science training in Bangalore
    Data science training in pune
    Data science online training
    Data Science Interview questions and answers
    Data Science Tutorial

    ReplyDelete
  3. Its really an Excellent post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog. Thanks for sharing....
    Best Devops Training in pune
    Devops Training in Bangalore
    Microsoft azure training in Bangalore
    Power bi training in Chennai

    ReplyDelete
  4. Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.
    Data Science Training in Chennai
    Robotic Process Automation Training in Chennai
    Cloud Computing Training in Chennai
    Data Warehousing Training in Chennai
    Dev Ops Training in Chennai

    ReplyDelete
  5. I have to voice my passion for your kindness giving support to those people that should have guidance on this important matter.
    AI training chennai | AI training class chennai
    Cloud computing training | cloud computing class chennai

    ReplyDelete