JDK-4733558 : LTP: java.beans.XMLEncoder does not serialize as xml java.sql.Date members
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.0,7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2002-08-19
  • Updated: 2010-07-09
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b03Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
Name: gm110360			Date: 08/19/2002


FULL PRODUCT VERSION :
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]

EXTRA RELEVANT SYSTEM CONFIGURATION :
j2sdk1.4.0_01

A DESCRIPTION OF THE PROBLEM :
The java.beans.XMLEncoder class does not serialize into xml
java.sql.Date members of an object.

However, it does serialize into xml java.util.Date members
of an object.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.Create any serializable class containing a java.sql.Date
member.
2.Try to serialize it to xml using XMLEncoder.writeObject()
and  then deserialize it from xml using XMLDecoder.readObject()
3. An error will result when deserializing because the
java.sql.Date member of the object was not serialized.


EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected the object including the date member of the object
to be serialized and then deserialized back.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Encoding completed....
ColInfo@e9cb75
Decoding completed....
java.lang.InstantiationException: java.sql.Date
Continuing ...
java.lang.RuntimeException: failed to evaluate: <unbound>=Date.new();
Continuing ...


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * EncodeDecodeXML.java
 *
 * Created on August 16, 2002, 9:29 AM
 */
import javax.swing.JButton;
import java.io.*;
import java.beans.XMLEncoder;
import java.beans.XMLDecoder;

/**
 *
 * @author  gxm001
 */
public class EncodeDecodeXML {
    
    /** Creates a new instance of EncodeXML */
    public EncodeDecodeXML() {
    }
    
    public static void main(String[] args){
        
        ColInfo colinfo = new ColInfo();
        colinfo.primaryKey = true;
        colinfo.colType = 1;
        colinfo.colName = "My_Column_name2";
        colinfo.object = new java.lang.Character('A');
        
        colinfo.buf = new StringBuffer("My stringbuffer test string");
        
        colinfo.date = new java.sql.Date(System.currentTimeMillis());
        
        try{
            XMLEncoder enc = new XMLEncoder( new BufferedOutputStream( new
FileOutputStream("Test.xml")));
            enc.writeObject(colinfo);
            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();
        }
        
    }
    
}

 * Copyright 2002
 *
 * UMB Bank, n.a.
 * All Rights Reserved
 */

/**
 * Description of the Class
 *
 * @author $Author: mks001 $
 * @version $Revision: 1.1 $ $Date: 2002/07/12 20:09:51 $
 * @since July 9, 2002
 */
public final class ColInfo implements java.io.Serializable
{

    public Object getObject() {
        return object;
    }

    public void setObject( Object object ) {
        this.object = object;
    }

    public StringBuffer getBuf() {
        return buf;
    }

    public void setBuf( StringBuffer buf ) {
        this.buf = buf;
    }
    
    public void setDate( java.sql.Date date ) {
        this.date = date;
    }
    
    public java.sql.Date getDate() {
        return date;
    }

    public java.sql.Date date;

    public Object object;
    
    public StringBuffer buf;
    
    /**
     * Description of the Field
     *
     * @since June 25, 2002
     */
    public String colName;

    /**
     * Description of the Field
     *
     * @since June 25, 2002
     */
    public int colType;

    /**
     * Description of the Field
     *
     * @since June 25, 2002
     */
    public boolean primaryKey;

    /**
     * Creates a new instance of ColInfo
     *
     * @since July 9, 2002
     */
    public ColInfo()
    {
        super();
    }

    /**
     * Getter for property colName.
     *
     * @return Value of property colName.
     * @since July 9, 2002
     */
    public java.lang.String getColName()
    {
        return colName;
    }

    /**
     * Setter for property colName.
     *
     * @param colName New value of property colName.
     * @since July 9, 2002
     */
    public void setColName( java.lang.String colName )
    {
        this.colName = colName;
    }

    /**
     * Getter for property colType.
     *
     * @return Value of property colType.
     * @since July 9, 2002
     */
    public int getColType()
    {
        return colType;
    }

    /**
     * Setter for property colType.
     *
     * @param colType New value of property colType.
     * @since July 9, 2002
     */
    public void setColType( int colType )
    {
        this.colType = colType;
    }

    /**
     * Gets the JavaType attribute of the ColInfo object
     *
     * @return The JavaType value
     * @since June 25, 2002
     */
    public final String getJavaType()
    {
        switch ( colType )
        {
            case java.sql.Types.CHAR:
            case java.sql.Types.LONGVARCHAR:
            case java.sql.Types.VARCHAR:
                return "java.lang.String";
            case java.sql.Types.BIGINT:
            case java.sql.Types.INTEGER:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.TINYINT:
            case java.sql.Types.DECIMAL:
            case java.sql.Types.DOUBLE:
            case java.sql.Types.FLOAT:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.REAL:
                return "java.math.BigDecimal";
            case java.sql.Types.DATE:
            case java.sql.Types.TIME:
            case java.sql.Types.TIMESTAMP:
                return "java.sql.Timestamp";
            default:
                return "byte[]";
        } //end switch
    }

    /**
     * Setter for property primaryKey.
     *
     * @param primaryKey New value of property primaryKey.
     * @since July 9, 2002
     */
    public void setPrimaryKey( boolean primaryKey )
    {
        this.primaryKey = primaryKey;
    }

    /**
     * Getter for property primaryKey.
     *
     * @return Value of property primaryKey.
     * @since July 9, 2002
     */
    public boolean isPrimaryKey()
    {
        return primaryKey;
    }

    /**
     * Gets the SQLGetter attribute of the ColInfo object
     *
     * @return The SQLGetter value
     * @since June 25, 2002
     */
    public final String getSQLGetter()
    {
        switch ( colType )
        {
            case java.sql.Types.CHAR:
            case java.sql.Types.LONGVARCHAR:
            case java.sql.Types.VARCHAR:
                return "getString";
            case java.sql.Types.BIGINT:
            case java.sql.Types.INTEGER:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.TINYINT:
            case java.sql.Types.DECIMAL:
            case java.sql.Types.DOUBLE:
            case java.sql.Types.FLOAT:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.REAL:
                return "getBigDecimal";
            case java.sql.Types.DATE:
            case java.sql.Types.TIME:
            case java.sql.Types.TIMESTAMP:
                return "getTimestamp";
            default:
                return "getBytes";
        } //end switch
    }

    /**
     * Gets the SQLSetter attribute of the ColInfo object
     *
     * @return The SQLSetter value
     * @since June 25, 2002
     */
    public final String getSQLSetter()
    {
        switch ( colType )
        {
            case java.sql.Types.CHAR:
            case java.sql.Types.LONGVARCHAR:
            case java.sql.Types.VARCHAR:
                return "setString";
            case java.sql.Types.BIGINT:
            case java.sql.Types.INTEGER:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.TINYINT:
            case java.sql.Types.DECIMAL:
            case java.sql.Types.DOUBLE:
            case java.sql.Types.FLOAT:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.REAL:
                return "setBigDecimal";
            case java.sql.Types.DATE:
            case java.sql.Types.TIME:
            case java.sql.Types.TIMESTAMP:
                return "setTimestamp";
            default:
                return "setBytes";
        } //end switch
    }

    /**
     * Gets the SQLType attribute of the ColInfo object
     *
     * @return The SQLType value
     * @since July 11, 2002
     */
    public final String getSQLType()
    {
        switch ( colType )
        {
            case java.sql.Types.CHAR:
                return "CHAR";
            case java.sql.Types.LONGVARCHAR:
                return "LONGVARCHAR";
            case java.sql.Types.VARCHAR:
                return "VARCHAR";
            case java.sql.Types.BIGINT:
                return "BIGINT";
            case java.sql.Types.INTEGER:
                return "INTEGER";
            case java.sql.Types.SMALLINT:
                return "SMALLINT";
            case java.sql.Types.TINYINT:
                return "TINYINT";
            case java.sql.Types.DECIMAL:
                return "DECIMAL";
            case java.sql.Types.DOUBLE:
                return "DOUBLE";
            case java.sql.Types.FLOAT:
                return "FLOAT";
            case java.sql.Types.NUMERIC:
                return "NUMERIC";
            case java.sql.Types.REAL:
                return "REAL";
            case java.sql.Types.DATE:
                return "DATE";
            case java.sql.Types.TIME:
                return "TIME";
            case java.sql.Types.TIMESTAMP:
                return "TIMESTAMP";
            default:
                return "BINARY";
        } //end switch
    }
}


This is the serialized object:

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.0_01" class="java.beans.XMLDecoder">
 <object class="ColInfo">
  <void property="buf">
   <object class="java.lang.StringBuffer"/>
  </void>
  <void property="colName">
   <string>My_Column_name2</string>
  </void>
  <void property="colType">
   <int>1</int>
  </void>
  <void property="object">
   <char>A</char>
  </void>
  <void property="primaryKey">
   <boolean>true</boolean>
  </void>
 </object>
</java>



---------- END SOURCE ----------
(Review ID: 160881) 
======================================================================

Comments
EVALUATION Specific persistence delegates were added.
01-09-2006

SUGGESTED FIX We should add the following persistence delegate: final class java_util_Date_PersistenceDelegate extends PersistenceDelegate { protected Expression instantiate(Object oldInstance, Encoder out) { Date date = (Date) oldInstance; return new Expression(date, date.getClass(), "new", new Object[] {date.getTime()}); } } -------------------------------------------------- Remove the following registartion, because it is not necessary: registerConstructor("java.util.Date", new String[]{"time"}); -------------------------------------------------- And register the same persistence delegate for java.sql.Date and java.sql.Time: // it is possible because java.util.Date is assignable from java.sql.Date and java.sql.Time internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate()); internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());
19-04-2006

EVALUATION Requires a persistence delegate. Will investigate. ###@###.### 2002-08-30
30-08-2002