Friday, March 21, 2014

Deserializing an Object in Java

This is a continuation of my previous post Serialization in Java

The code to deserialize is

import java.io.*;

public class Deserialize {

public static void main(String[] args) {
Employee e = null;

try {
FileInputStream fileIn =
new FileInputStream("C:\\Users\\arahi\\Desktop\\Temp\\test.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee)in.readObject();
in.close();
fileIn.close();

} catch (IOException ip) {
ip.printStackTrace();
return;
}

catch (ClassNotFoundException fnf) {
System.out.println("Employee class not found");
fnf.printStackTrace();
return;
}


System.out.println("EmpName: " + e.name);
System.out.println("Designation: " + e.designation);
System.out.println("Technology: " + e.technology);
System.out.println("Department: " + e.department);
}
}



There are only two things to note down here


e = (Employee)in.readObject();

Here since e is an object we are typecasting the value that we are reading from the file to Employee object.

Finally if you will run this code you will get following output

EmpName: Arpit Rahi
Designation: Consultant
Technology: FMW
Department: null
Process exited with exit code 0.


Here you can observer that Department has come as null as we have chosen department to be transient and hence it was not serialized.

Just to test you can remove the transient qualifier from the department.. try to serialize and deserialize and you will get the value for department as well.


So we have now understood the concept of serialization and desrialization however the concept of serialVersionUID is still not clear with this example as we have written the serialization code in a class which implements the java.io.Serializable


To understand it in a better way we will just modify our code a bit.

Now Serialization code will be


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

public class Employee implements java.io.Serializable {
String name;
String designation;
transient String department;
String technology;
static final long serialVersionUID =2L;



}
Compile this code and then

run the following code

import java.io.*;

public class Deserialize {

public static void main(String[] args) {

///Serialize the code
Employee e = new Employee();
e.name = "Arpit Rahi";
e.designation = "Consultant";
e.department = "Oracle";
e.technology = "FMW";
try {
FileOutputStream fileOut =
new FileOutputStream("C:\\Users\\arahi\\Desktop\\Temp\\test.txt");

ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Data Serialized");
} catch (IOException i) {
i.printStackTrace();
}

////Deserialize th

Employee ne = null;

try {
FileInputStream fileIn =
new FileInputStream("C:\\Users\\arahi\\Desktop\\Temp\\test.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
ne = (Employee)in.readObject();
in.close();
fileIn.close();

} catch (IOException ip) {
ip.printStackTrace();
return;
}

catch (ClassNotFoundException fnf) {
System.out.println("Employee class not found");
fnf.printStackTrace();
return;
}


System.out.println("EmpName: " + ne.name);
System.out.println("Designation: " + ne.designation);
System.out.println("Technology: " + ne.technology);
System.out.println("Department: " + ne.department);
}
}


Now just try to change the serialVersionUID and recompile the code


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

public class Employee implements java.io.Serializable {
String name;
String designation;
transient String department;
String technology;
static final long serialVersionUID =3L;



}

Now just try to read the code -->here you can use the previous code to read just comment out the part which is trying to write

import java.io.*;

public class Deserialize {

public static void main(String[] args) {

///Serialize the code
// Employee e = new Employee();
// e.name = "Arpit Rahi";
// e.designation = "Consultant";
// e.department = "Oracle";
// e.technology = "FMW";
// try {
// FileOutputStream fileOut =
// new FileOutputStream("C:\\Users\\arahi\\Desktop\\Temp\\test.txt");
//
// ObjectOutputStream out = new ObjectOutputStream(fileOut);
// out.writeObject(e);
// out.close();
// fileOut.close();
// System.out.printf("Data Serialized");
// } catch (IOException i) {
// i.printStackTrace();
// }

////Deserialize th

Employee ne = null;

try {
FileInputStream fileIn =
new FileInputStream("C:\\Users\\arahi\\Desktop\\Temp\\test.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
ne = (Employee)in.readObject();
in.close();
fileIn.close();

} catch (IOException ip) {
ip.printStackTrace();
return;
}

catch (ClassNotFoundException fnf) {
System.out.println("Employee class not found");
fnf.printStackTrace();
return;
}


System.out.println("EmpName: " + ne.name);
System.out.println("Designation: " + ne.designation);
System.out.println("Technology: " + ne.technology);
System.out.println("Department: " + ne.department);
}
}



Now run the code you will get the following error

java.io.InvalidClassException: Employee; local class incompatible: stream classdesc serialVersionUID = 2, local class serialVersionUID = 3
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at Deserialize.main(Deserialize.java:34)
Process exited with exit code 0.


This is because the object which was last serialized was with a version of 3 and now when we are trying to retrieve it with a version of 2 so a mismatch and hence this error.

To overcome this issue you can again serialize with the latest version and then try to deserialize it.

No comments: