Friday, September 7, 2007

Object Serialization with XMLEncoder

Java API provides XMLEncoder class as an alternative to the ObjectOutputStream and can used to generate a textual representation of a JavaBean in the same way that the ObjectOutputStream can be used to create binary representation of Serializable objects. For example, the following fragment can be used to create a textual representation the supplied JavaBean and all its properties.

XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("Test.xml")));
e.writeObject(new JButton("Hello, world"));
e.close();

The XMLEncoder class provides a default denotation for JavaBeans in which they are represented as XML documents complying with version 1.0 of the XML specification and the UTF-8 character encoding of the Unicode/ISO 10646 character set.

The XML syntax uses the following conventions:
  • Each element represents a method call.
  • The "object" tag denotes an expression whose value is to be used as the argument to the enclosing element.
  • The "void" tag denotes a statement which will be executed, but whose result will not be used as an argument to the enclosing method.
  • Elements which contain elements use those elements as arguments, unless they have the tag: "void".
  • The name of the method is denoted by the "method" attribute.
  • XML's standard "id" and "idref" attributes are used to make references to previous expressions - so as to deal with circularities in the object graph.
  • The "class" attribute is used to specify the target of a static method or constructor explicitly; its value being the fully qualified name of the class.
  • Elements with the "void" tag are executed using the outer context as the target if no target is defined by a "class" attribute.
  • Java's String class is treated specially and is written Hello, world where the characters of the string are converted to bytes using the UTF-8 character encoding.


The below code is a sample student bean class to demonstrate the Usage of XMLEncoder and XMLDecoder

Code:

import java.util.Date;

public class Student
{
private String name;
private int age;
private int[] marks_M_P_C;
private String fatherName;
private int rollNumber;
private Date joinDate;

public Date getJoinDate() {
return joinDate;
}
public void setJoinDate(Date joinDate) {
this.joinDate = joinDate;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFatherName() {
return fatherName;
}
public void setFatherName(String fatherName) {
this.fatherName = fatherName;
}
public int[] getMarks_M_P_C() {
return marks_M_P_C;
}
public void setMarks_M_P_C(int[] marks_M_P_C) {
this.marks_M_P_C = marks_M_P_C;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRollNumber() {
return rollNumber;
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}

public double getAvg(){
return (double)(this.getTotal()/3.0);
}

public double getTotal(){
return (double)(this.marks_M_P_C[0]+this.marks_M_P_C[1]+this.marks_M_P_C[2]);
}

public String toString() {
return getClass().getName() +
"[Marks=" + asString(marks_M_P_C) +
",avg=" + getAvg() +
",name=" + name +
",fatherName=" + fatherName +
"rollNumber" + rollNumber +
"age" + age + "]";
}

private String asString(int[] array) {
StringBuffer buffer = new StringBuffer("[");
for (int i=0, n=array.length; i < n; i++) {
if (i != 0) {
buffer.append(",");
}
buffer.append(array[i]);
}
buffer.append("]");
return buffer.toString();
}
}

The below code demonstrate the usage of XmlEncoder to store the object as well as XMLDecoder to Retrieve the object

Code:

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;

public class XmlObjTest {
public static void main (String args[]) throws Exception {
Student student = new Student();
student.setMarks_M_P_C(new int[] {146, 52, 53});
student.setName("Hari");
student.setJoinDate(new Date());
student.setRollNumber(1219);
student.setFatherName("Rao");
student.setAge(19);
XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("student.xml")));
encoder.writeObject(student);
encoder.close();

System.out.println(student);

XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream("student.xml")));
Student studentR = (Student)decoder.readObject();
decoder.close();
System.out.println(studentR);

}
}




The below show how an Object will be stored

Code: (student.xml)

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.5.0_08" class="java.beans.XMLDecoder">
<object class="temp.Student">
<void property="age">
<int>19</int>
</void>
<void property="fatherName">
<string>Rao</string>
</void>
<void property="joinDate">
<object class="java.util.Date">
<long>1189158030890</long>
</object>
</void>
<void property="marks_M_P_C">
<array class="int" length="3">
<void index="0">
<int>146</int>
</void>
<void index="1">
<int>52</int>
</void>
<void index="2">
<int>53</int>
</void>
</array>
</void>
<void property="name">
<string>Hari</string>
</void>
<void property="rollNumber">
<int>1219</int>
</void>
</object>
</java>