JDK-6921644 : XMLEncoder generates invalid XML
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.2,6u16
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2010-02-01
  • Updated: 2011-03-14
  • Resolved: 2010-03-17
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 b86Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
A special constellation of objects referencing each other with additional Integer wrapper objects is troubeling the java.beans.XMLEncoder. The serialized XML can be generated but it contains some wrong output and the XMLDecoder has problems decoding the generated XML.

The Integer wrapper from the field myParentGUTA_ID from the Gliederung class seems to be the problem (see attached code). The problem seems to be associated with the caching abilities of the Integer wrapper class, because the whole thing works if the value in the Wrapper is >= 128 or a new Integer() object with any value is created and assigned to the field.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile and run attached classes(ExportTester.main())


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
the XMLDecoder should be able to decode the XML and throw no Exceptions
ACTUAL -
The xmlEncoder produces an invalid file. The XMLDecoder fails to decode this file and gives an error.





ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.Exception: Unbound variable: Integer0
Continuing ...
java.lang.NullPointerException
Continuing ...
java.lang.NoSuchMethodException: <unbound>=GliederungRS.getParentGUTA_ID(GliederungRS, null);
Continuing ...

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
The Testcase consists of five classes:

//-----CLASS1----

package xmlEncTest;

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


public class ExportTester implements ExceptionListener {

	public static void main(String[] args) throws Exception {
		new ExportTester().test();
	}
	
	
	public void test() throws Exception {
		// init
		GARS gars = new GARS();
		gars.setID(100); // it works if ID >= 128
		
		GliederungRS grs1 = new GliederungRS(gars);
		GliederungRS grs2 = new GliederungRS(gars);
		GliederungRS grs3 = new GliederungRS(gars);
		grs1.setID(5);
		grs2.setID(6);
		grs3.setID(7);
		grs3.setParentGUTA_ID(gars.getID());
		
		GAStundensatzRS stu = new GAStundensatzRS(gars);
		stu.setId(20);
		
		NKSPORS npo1 = new NKSPORS(gars);
		NKSPORS npo2 = new NKSPORS(gars);
		NKSPORS npo3 = new NKSPORS(gars);
		npo1.setID(15);
		npo2.setID(16);
		npo3.setID(17);

		npo2.setStundensatzRS(stu);
		npo3.setStundensatzRS(stu);
		grs1.addNKSPors(npo1);
		grs1.addNKSPors(npo2);
		grs3.addNKSPors(npo3);
		
		gars.addGliederung(grs1);
		gars.addGliederung(grs2);
		gars.addGliederung(grs3);

		stu.addNKSPors(npo2);
		stu.addNKSPors(npo3);
		
		// export to XML
		System.out.print("write file... ");
		String filename = "c:/test.xml";
		XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(filename)));
		e.setExceptionListener(this);
		e.writeObject(gars);
		e.close();
		System.out.println("done");
		
		// Import form XML
		System.out.print("read file... ");
		XMLDecoder dec = new XMLDecoder(new BufferedInputStream(new FileInputStream(filename)));
		GARS gars2 = (GARS)dec.readObject();
		dec.close();
		System.out.println("done");
	}


	public void exceptionThrown(Exception e) {
		e.printStackTrace();
		System.exit(0);
	}
}


//----CLASS2----

package xmlEncTest;

import java.util.Vector;

public class GARS {
    int myID;
    Vector myGliederungen = new Vector();

    public int getID() {
        return myID;
    }

    public void setID(int i) {
        myID = i;
    }
    
    public Vector getGliederungen(){
    	return myGliederungen;
    }
    public void setGliederungen(Vector d){
    	myGliederungen = d;
    }
    public void addGliederung(GliederungRS rs) {
    	myGliederungen.add(rs);
    	rs.setGARS(this);
    	rs.setGUTA_ID(this.getID());
    }

    public GARS() {
        myID = 0;
    }
}

//----CLASS3----

package xmlEncTest;

import java.util.Vector;

public class GliederungRS {
	private int myID;
	private int  myGUTA_ID;
	private GARS myGARS;
	private Integer myParentGUTA_ID;

	private Vector nkspors = new Vector();

	public GliederungRS(){
		myID=0;
		myGUTA_ID=-1;
	}
	
	public GliederungRS(GARS guta){
		setID(0);
		setGARS(guta);
		setGUTA_ID(guta.getID());
	}

	public GARS getGARS() {
		return myGARS;
	}

	public void setGARS(GARS gars) {
		this.myGARS = gars;
		myGUTA_ID = gars.getID();
	}

	public Integer getGUTA_ID() {
		return myGUTA_ID;
	}

	public void setGUTA_ID(Integer myGUTA_ID) {
		this.myGUTA_ID = myGUTA_ID;
	}

	public int getID() {
		return myID;
	}

	public void setID(int myID) {
		this.myID = myID;
	}

	public Integer getParentGUTA_ID() {
		return myParentGUTA_ID;
	}

	public void setParentGUTA_ID(Integer parentGUTA_ID) {
		myParentGUTA_ID = parentGUTA_ID;
	}

	public Vector getNkspors() {
		return nkspors;
	}

	public void setNkspors(Vector nkspors) {
		this.nkspors = nkspors;
	}

	public void addNKSPors(NKSPORS nkpo) {
		nkspors.add(nkpo);
		nkpo.setGliederungRS(this);
	}
}

//----CLASS4----

package xmlEncTest;

import java.util.Vector;

public class GAStundensatzRS {
	private int myId;
	private GARS gars;
	private Vector myNKSPors = new Vector();
	
	public GAStundensatzRS() {
		myId= 0;
	}
	
	public GAStundensatzRS(GARS gars) {
		this();
		setGars(gars);
	}

	public int getId() {
		return myId;
	}

	public void setId(int id) {
		myId = id;
	}

	public void setGars(GARS gars) {
		this.gars = gars;
	}
	public GARS getGars() {
		return gars;
	}

	public Vector getNKSPors() {
		return myNKSPors;
	}

	public void setNKSPors(Vector pors) {
		myNKSPors = pors;
	}
	
	public void addNKSPors(NKSPORS nkpo) {
		nkpo.setStundensatzRS(this);
		getNKSPors().add(nkpo);
	}
}

//----CLASS5----

package xmlEncTest;

public class NKSPORS {
    int myID;
    int myGUTA_ID;
    Integer myGLIED_ID;
    GAStundensatzRS myStundensatzRS;
    GliederungRS myGliederungRS;
    GARS myGARS;

    public NKSPORS() {
    	myID = 0;
    }

    public NKSPORS(GARS gars) {
        myID = 0;
        setGARS(gars);
    }

    public void setGARS(GARS g) {myGARS = g; }

    public GARS getGARS() {
        return myGARS;
    }

    public void setID(int id) {
        myID = id;
    }

    public int getID() {
        return myID;
    }

	public GliederungRS getGliederungRS(){
		return myGliederungRS;
	}
	public void setGliederungRS(GliederungRS rs){
		myGliederungRS = rs;
	}

	public GAStundensatzRS getStundensatzRS() {
		return myStundensatzRS;
	}

	public void setStundensatzRS(GAStundensatzRS stundensatzRS) {
		myStundensatzRS = stundensatzRS;
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
use Integer a = new Integer(123) instead of Integer a = 123; when assigning make a new object (new Integer(x))  or use Integers > 127 (which is not always possible), use another xml serializer (xstream)

Comments
EVALUATION To fix these bugs we should mark statements in correct order and calculate identifier after processing subelements. Statements assigned to the specific value should be processed only once, so we should remove them from the list after the processing. Objects referenced to the identifier should also process all statement to ensure that all properties are initialized correctly.
03-03-2010

EVALUATION Second problems are described in the 5023550 CR and the 5023557 CR. All these problems could be fixed together.
24-02-2010

EVALUATION There are several problems. First problem in the generator of id/idref attribute.
05-02-2010