I recently upgraded to Java 7 and I am noticing a strange issue with the XML serialization. Basically, I've a test utility class that does an Object to XML conversion using the XML encoder.
See sample code below:
public static String toXML(Object obj) {
String retval = null;
if(obj != null) {
XMLEncoder encoder = null;
ByteArrayOutputStream bos;
try {
bos = new ByteArrayOutputStream();
encoder = new XMLEncoder(bos);
encoder.writeObject(obj);
encoder.close();
byte[] bytes = bos.toByteArray();
if(bytes != null) {
retval = new String(bytes);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if(encoder != null) {
encoder.close();
}
}
}
return retval;
}
Which worked fine with Java 1.6, however ever since I upgraded to Java 1.7 I've noticed the XML encoder operation throws an IOException in logs:
java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:45)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:140)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.beans.XMLEncoder.flush(XMLEncoder.java:497)
at java.beans.XMLEncoder.close(XMLEncoder.java:530)
at com.mytestcode.server.common.util.TestSerializer.toXML(TestSerializer.java:87)
I looked into the XMLEncoder code and found that StreamEncoder.ensureOpen has a check for isOpen which seems to be coming up as false.
This question looks similar although it is not using the Java 1.7 XML encoder. I've not seen this issue with the XML encoder or with this method in general, is there something I can fix in code or does this seem more downstream? What am I missing?
I was finally able to figure this one out. The trouble was because of Java 6 to 7 upgarde.
Diff betweem Java 6 and 7, XMLEncoder shows that in Java 6 the XML encoder works directly on the ByteArrayOutputStream passed in constructor, whereas in Java 7 the XMLEncoder wraps a StreamEncoder around the ByteArrayOutputStream passed in constructor.
(Line 289)
While calling a ByteArrayOutputStream.close() (see Javadoc) does absolutely nothing, a StreamEncoder.close() (see Javadoc) throws a recoverable IOException if the Stream is already closed.
This exception is picked up the the default ExceptionListener and gets logged in the logs.