Friday, 25 October 2013

Java XMLEncoder issue with java.sql.Timestamp in JDK 5 and 6

Objective

To highlight XMLEncoder class issue with java.sql.Timestamp class in JDK 5 and 6.

Environment

Java 5 and 6

Issue

From Java 5 we have XMLEncoder and XMLDecoder class to deal with XML encoding and decoding; but if you have observed the java.sql.Timestamp class is not taken care correctly by these classes, the following example is to show the same:

Program

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.sql.Timestamp;
import java.util.Date;

/**
 * @author mchopker
 *
 */
public class TestXMLEnocdingIssue {

    public static void main(String[] args) {
        try {
            XMLEncoder enc = new XMLEncoder(new BufferedOutputStream(
                    new FileOutputStream("Test.xml")));
            Person person = new Person("Mahesh", new Timestamp(
                    new Date().getTime()));
            enc.writeObject(person);
            enc.close();
            System.out.println("Encoding completed....");
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            XMLDecoder dec = new XMLDecoder(new BufferedInputStream(
                    new FileInputStream("Test.xml")));
            Object result = dec.readObject();
            dec.close();
            System.out.println(result);
            System.out.println("Decoding completed....");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

---
import java.io.Serializable;
import java.sql.Timestamp;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Timestamp time;
    public Timestamp getTime() {
        return time;
    }
    public void setTime(Timestamp time) {
        this.time = time;
    }
    public Person() {
    }
    public Person(String string, Timestamp time) {
        this.name = string;
        this.time = time;
    }
    public String getName() {
        return name;
    }
    public void setName(String string) {
        this.name = string;
    }
}

Console Output

java.lang.InstantiationException: java.sql.Timestamp
Continuing ...
java.lang.RuntimeException: failed to evaluate: <unbound>=Class.new();
Continuing ...

Encoding completed....
Person@6bdd46f7
Decoding completed....

XML Output

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.5.0_15" class="java.beans.XMLDecoder">
 <object class="Person">
  <void property="name">
   <string>Mahesh</string>
  </void>
 </object>
</java>

Observation

You can notice the exception shown as red color text, this is thrown by Java itself and the resulting XML not containing the timestamp attribute; the reason java.sql.Timestamp class is not taken care by Java 5/6 and is fixed now in Java 7. 
If you still happens to use Java 5/6 for some reason then you might have to write custom persistence delegate to deal with this issue as mentioned here:

Thank You!