XStream

Incompatibility between Sun Java 1.5 and 1.4.2

Details

  • Type: Bug Bug
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • JDK version and platform:
    Sun Java 1.5/1.4.2 on Windows and Linux

Description

I don't know if it's really a bug, but we encountered some incompatibilities between Java 1.4.2 and Java 1.5 using xstream-1.1 (using the PureJavaReflectionProvider).

We are using xml-messages (generated by xstream) to communicate between a server and numerous clients. The server is running on Suns JVM 1.4.2 while some of the clients have upgraded to Java 1.5 in the meantime.

We are serializing an Object having a member of the type List. this member is initialized with:
member = Collections.synchronizedList( new ArrayList());

If we serialize that class on 1.4.2, it cannot be deserialized on 1.5.
The other way around it is also not possible to deserialize the xml code generated on 1.4.2.

It seems to have something to do with renamings of internal classes:
1.4.2: java.util.Collections$SynchronizedRandomAccessList
1.5.0: java.util.collections$SynchronizedList

With the two classes appended to the end of that message, the error can easily be reproduced.

It whould be nice if somebody of you can give me a feedback concerning the problem. One solution for us may be to use a Vector instead of a List, but this would be hard to realize because every client running a non-up-to-date version would be unable to use our software...

thank you,
Andreas Wetzel

// start XStreamTest.java
public class XStreamTest
{
private XStream myXStream;

public XStreamTest()

{ myXStream = new XStream( new PureJavaReflectionProvider(), new DomDriver()); }

private void writeXML()

{ System.out.println( myXStream.toXML( new ResultSet())); }

private void readXML( File f) throws FileNotFoundException

{ FileReader reader = new FileReader( f); ResultSet set = (ResultSet) myXStream.fromXML( reader); System.out.println( set.toString()); }

public static void main( String[] args)
{
XStreamTest test = new XStreamTest();

if ( args.length == 1 ) {
File f = new File( args[0]);
if ( f.exists() ) {
try { test.readXML( f); return; }
catch( FileNotFoundException e) {
}
}
}
test.writeXML();
}
}
// end XStreamTest.java

// start ResultSet.java
public class ResultSet
{
List results;

public ResultSet()

{ results = Collections.synchronizedList( new ArrayList()); results.add( "foo"); results.add( "bar"); }

public String toString()
{
StringBuffer buffer = new StringBuffer();
for (Iterator it = results.iterator(); it.hasNext() { buffer.append( (String) it.next()).append( "\n"); }
return buffer.toString();
}
}
// end ResultSet.java

Activity

Hide
Joe Walnes added a comment -

If the difference between the synchronized list implementations between 1.4 and 1.5 is just a rename, you might be able to get away with using an alias.

Something like:

xstream.alias("java.util.Collections-SynchronizedList", Class.forName("java.util.Collections$SynchronizedRandomAccessList"));

Will force XStream to write SynchronizedRandomAccessList as SynchronizedList. Depending which way you are going, you may need to do the opposite.

If this approach doesn't work, you will probably have to either create a custom Converter implementation that automatically does the migration or perform some pre/post processing on the XML to alter it.

Show
Joe Walnes added a comment - If the difference between the synchronized list implementations between 1.4 and 1.5 is just a rename, you might be able to get away with using an alias. Something like: xstream.alias("java.util.Collections-SynchronizedList", Class.forName("java.util.Collections$SynchronizedRandomAccessList")); Will force XStream to write SynchronizedRandomAccessList as SynchronizedList. Depending which way you are going, you may need to do the opposite. If this approach doesn't work, you will probably have to either create a custom Converter implementation that automatically does the migration or perform some pre/post processing on the XML to alter it.
Hide
Joerg Schaible added a comment -

It's a lot more than just a new name. Look at the acceptance test for collections and you know, what I mean.

Show
Joerg Schaible added a comment - It's a lot more than just a new name. Look at the acceptance test for collections and you know, what I mean.
Hide
Jens Schumacher added a comment -

Is there a known workaround for this problem?

We are currently using XStream to serialize a custom object containing two private variables:

private String name;
private List tasks;

After upgrading to Java 1.5 those objects can not be restored and the following exception is thrown:

com.thoughtworks.xstream.converters.ConversionException: Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList
---- Debugging information ----
required-type : java.util.Collections$SynchronizedRandomAccessList
cause-message : Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList
class : com.atlassian.confluence.extra.dynamictasklist.model.TaskList
message : Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList
line number : 3
path : /com.atlassian.confluence.extra.dynamictasklist.model.TaskList/tasks
cause-exception : com.thoughtworks.xstream.converters.reflection.ObjectAccessException

Show
Jens Schumacher added a comment - Is there a known workaround for this problem? We are currently using XStream to serialize a custom object containing two private variables: private String name; private List tasks; After upgrading to Java 1.5 those objects can not be restored and the following exception is thrown: com.thoughtworks.xstream.converters.ConversionException: Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList ---- Debugging information ---- required-type : java.util.Collections$SynchronizedRandomAccessList cause-message : Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList class : com.atlassian.confluence.extra.dynamictasklist.model.TaskList message : Cannot construct java.util.Collections$SynchronizedRandomAccessList: java.util.Collections$SynchronizedRandomAccessList line number : 3 path : /com.atlassian.confluence.extra.dynamictasklist.model.TaskList/tasks cause-exception : com.thoughtworks.xstream.converters.reflection.ObjectAccessException
Hide
Joerg Schaible added a comment -

I had a look at the issue and the problem is, that the synchronized collections in JDK 1.5 use a custom serialization, while they don't have this in JDK 1.4. This leads unfortunately to a complete different XML representation. Please try this as workaround:

final Class synchronizedRandomAccessList = Class.forName("java.util.Collections$SynchronizedRandomAccessList");
xstream.register( 
    new ReflectionConverter(xstream.getMapper(), new JVM().bestReflectionProvider()) {

    public boolean canConvert(Class type) {
        return type == synchronizedRandomAccessList;
    }
});
Show
Joerg Schaible added a comment - I had a look at the issue and the problem is, that the synchronized collections in JDK 1.5 use a custom serialization, while they don't have this in JDK 1.4. This leads unfortunately to a complete different XML representation. Please try this as workaround:
final Class synchronizedRandomAccessList = Class.forName("java.util.Collections$SynchronizedRandomAccessList");
xstream.register( 
    new ReflectionConverter(xstream.getMapper(), new JVM().bestReflectionProvider()) {

    public boolean canConvert(Class type) {
        return type == synchronizedRandomAccessList;
    }
});
Hide
pavel niedoba added a comment -

Andreas

I think you have to reconsider your design, because xstream with reflection converter does not provide cross version compatibility. U dont probably use jdk 1.3, but you should know that Vector class is not compatible between version 1.3 and 1.4

Show
pavel niedoba added a comment - Andreas I think you have to reconsider your design, because xstream with reflection converter does not provide cross version compatibility. U dont probably use jdk 1.3, but you should know that Vector class is not compatible between version 1.3 and 1.4
Hide
Matthias Nott added a comment -

Joerg,

is there any update on this? I'm serializing object between a servlet and an applet, and I cannot guarantee for the same version of Java on both sides. I have to transfer a list of objects, and I wonder about alternatives. Sounds like the whole idea of xstream would not work for an applet?

Tnx,

M

Show
Matthias Nott added a comment - Joerg, is there any update on this? I'm serializing object between a servlet and an applet, and I cannot guarantee for the same version of Java on both sides. I have to transfer a list of objects, and I wonder about alternatives. Sounds like the whole idea of xstream would not work for an applet? Tnx, M
Hide
Joerg Schaible added a comment -

Matthias, please ask questions on the user list. Depending on your use case, you have different options.

Show
Joerg Schaible added a comment - Matthias, please ask questions on the user list. Depending on your use case, you have different options.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: