XStream

Comparing uninitialized objects

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.2.2
  • Fix Version/s: 1.3
  • Component/s: Converters, Core
  • Labels:
    None
  • JDK version and platform:
    Sun 1.5.0_11 for Windows

Description

Below is the minimal case for the problem I came across. During deserialization NPE is thrown from compareTo method, probably because object is put in the tree before id is filled. Simple workaround is to change the order of the fields, but sometimes it's not possible (for example when field is inherited).

import java.util.Set;
import java.util.TreeSet;
import junit.framework.TestCase;
import com.thoughtworks.xstream.XStream;

public class Test extends TestCase {
XStream xs = new XStream();

public void test() { C c = new C(1); c.others.add(c); c.others.add(new C(2)); xs.fromXML(xs.toXML(c)); }
}

class C implements Comparable {
Set<C> others = new TreeSet<C>();
final Integer id;

C(Integer id) { this.id = id; }

public int compareTo(Object o) { return id.compareTo(((C) o).id); }
}

Activity

Hide
Joerg Schaible added a comment -

Since XStream 1.2.2 you can set the order in which the fields are saved (see FAQ). Starting with 1.3 the inherited fields will be saved first (see announcement of 1.2.2 release).

Show
Joerg Schaible added a comment - Since XStream 1.2.2 you can set the order in which the fields are saved (see FAQ). Starting with 1.3 the inherited fields will be saved first (see announcement of 1.2.2 release).
Hide
Jerzy Smyczek added a comment -

This modified case fails regardless of field order:

import java.util.Set;
import java.util.TreeSet;
import junit.framework.TestCase;
import com.thoughtworks.xstream.XStream;

public class Test extends TestCase {
XStream xs = new XStream();

public void test() { C c = new C(1); c.others.add(c); c.others.add(new C(1)); /* same id */ xs.fromXML(xs.toXML(c)); }
}

class C implements Comparable {
final Integer id;
final Set<C> others = new TreeSet<C>();

C(Integer id) { this.id = id; }

public int compareTo(Object o) {
C c = (C) o;
int cmp = id.compareTo(c.id);
if (cmp != 0) { return cmp; } else { return new Integer(others.size()).compareTo(c.others.size()); }
}
}

Show
Jerzy Smyczek added a comment - This modified case fails regardless of field order: import java.util.Set; import java.util.TreeSet; import junit.framework.TestCase; import com.thoughtworks.xstream.XStream; public class Test extends TestCase { XStream xs = new XStream(); public void test() { C c = new C(1); c.others.add(c); c.others.add(new C(1)); /* same id */ xs.fromXML(xs.toXML(c)); } } class C implements Comparable { final Integer id; final Set<C> others = new TreeSet<C>(); C(Integer id) { this.id = id; } public int compareTo(Object o) { C c = (C) o; int cmp = id.compareTo(c.id); if (cmp != 0) { return cmp; } else { return new Integer(others.size()).compareTo(c.others.size()); } } }
Hide
Joerg Schaible added a comment -

You're right, your second case also failed with the head revision. I've tested the same case with JDK serialization and had to recognize that they succeed. Main reason was, that the JDK contains an optimized functionality when a presorted set is added into an empty TreeSet. I changed the implementation of the TreeSetConverter (and TreeMapConverter) to behave the same. You may give the latest head revision a try.

Show
Joerg Schaible added a comment - You're right, your second case also failed with the head revision. I've tested the same case with JDK serialization and had to recognize that they succeed. Main reason was, that the JDK contains an optimized functionality when a presorted set is added into an empty TreeSet. I changed the implementation of the TreeSetConverter (and TreeMapConverter) to behave the same. You may give the latest head revision a try.
Hide
Joerg Schaible added a comment -

Closing issues before next release.

Show
Joerg Schaible added a comment - Closing issues before next release.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: