Hi XStream team,

First of all 1000000 thanks for the excellent product.
I have been using XStream since 2007 and it has become a heart of many my projects.

Few days ago i mentioned that in some special cases calls of

        XStream.addImpliciteCollection
        (
            Class  definedIn,
            String collectionFieldName,
            Class  itemType
         )

delivered unexpected results.

Assume we have the following class hierarchy

   public class Parent
        extends Object
   {
        public ArrayList<I> parentCollection = null;
   }

   public class Child1
        extends Parent
   {
        public ArrayList<I> child1Collection = null;
   }

   public class Child2
        extends Parent
   {
        public ArrayList<I> child2Collection = null;
   }


and the following XStream setup:

        private final static XStream setupSerializer()
        {
            final XStream s = new XStream
            (
                new PureJavaReflectionProvider(), new DomDriver()
            );

            // Parent
            s.alias("parent", Parent.class);
            s.addImplicitCollection(Parent.class, "parentCollection",
   I.class);

            // Child1
            s.alias("child1", Child1.class);
            s.addImplicitCollection(Child1.class, "child1Collection",
   I.class);

            // Child2
            s.alias("child2", Child2.class);
            s.addImplicitCollection(Child2.class, "child2Collection",
   I.class);

            // IImpl1
            s.alias("i1", IImpl1.class);

            // IImpl2
            s.alias("i2", IImpl2.class);

            return s;
        }

then an attempt to deserialize the string "<child1><i1/><i2/><i1/></child1>"
leads to the following exception:

       com.thoughtworks.xstream.converters.ConversionException: No such
       field com.vn.xml.serialization.Child1.child2Collection : No such
       field com.vn.xml.serialization.Child1.child2Collection
       ---- Debugging information ----
       message             : No such field
       com.vn.xml.serialization.Child1.child2Collection
       cause-exception     :
       com.thoughtworks.xstream.converters.reflection.ObjectAccessException
       cause-message       : No such field
       com.vn.xml.serialization.Child1.child2Collection
       class               : com.vn.xml.serialization.Child1
       required-type       : com.vn.xml.serialization.Child1
       path                : /child1/i1
       -------------------------------
            at
       
com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:89)
            at
       
com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:63)
            at
       
com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:76)
            at
       
com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:60)
            at
       
com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:137)
            at
       
com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:33)
            at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:923)
            at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:909)
            at com.thoughtworks.xstream.XStream.fromXML(XStream.java:853)
            at com.thoughtworks.xstream.XStream.fromXML(XStream.java:845)
            at
       
com.vn.xml.serialization.ImpliciteCollectionsTest.testImpliciteCollection(ImpliciteCollectionsTest.java:25)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at
       
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at
       
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at junit.framework.TestCase.runTest(TestCase.java:154)
            at junit.framework.TestCase.runBare(TestCase.java:127)
            at junit.framework.TestResult$1.protect(TestResult.java:106)
            at junit.framework.TestResult.runProtected(TestResult.java:124)
            at junit.framework.TestResult.run(TestResult.java:109)
            at junit.framework.TestCase.run(TestCase.java:118)
            at
       
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
            at
       
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
            at
       
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
            at
       
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
            at
       
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
            at
       
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
       Caused by:
       com.thoughtworks.xstream.converters.reflection.ObjectAccessException:
       No such field com.vn.xml.serialization.Child1.child2Collection
            at
       
com.thoughtworks.xstream.converters.reflection.FieldDictionary.field(FieldDictionary.java:94)
            at
       
com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.getFieldType(PureJavaReflectionProvider.java:151)
            at
       
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.writeValueToImplicitCollection(AbstractReflectionConverter.java:264)
            at
       
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:236)
            at
       
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:162)
            at
       
com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:82)
            ... 26 more


Changing setup sequence to Child1/Child2/Parent solves the problem.

Simple JUnit is attached to mail.

Thank you in advance and hope to here you soon.


import java.util.ArrayList;

import junit.framework.TestCase;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.io.xml.DomDriver;

public final class ImpliciteCollectionsTest 
	extends TestCase 
{
	public interface I 
	{
		public String getId();
	}

	public static class Parent 
		extends Object
	{
		public ArrayList<I> parentCollection = null;
	}

	public static class Child1 
		extends Parent
	{
		public ArrayList<I> child1Collection = null;
	}
	
	public static class Child2 
		extends Parent
	{
		public ArrayList<I> child2Collection = null;
	}

	public final static class IImpl1
		extends Object
		implements I 
	{
	
		@Override
		public final String getId() 
		{
			return "1";
		}
	
	}
	
	public final static class IImpl2
		extends Object
		implements I 
	{
	
		@Override
		public final String getId() 
		{
			return "2";
		}
	
	}	
	

	public final void testImpliciteCollection()
	{
		final XStream s = setupSerializer();
		
		final Child2 child2 = (Child2)s.fromXML
		(
			"<child2><i1/><i2/><i1/></child2>"	
		);
		
		assertNull("parentCollection", child2.parentCollection);
		assertNotNull("child2Collection", child2.child2Collection);
		assertEquals("child2Collection.size()", 3, child2.child2Collection.size());		

		final Child1 child1 = (Child1)s.fromXML
		(
			"<child1><i1/><i2/><i1/></child1>"	
		);
		
		assertNull("parentCollection", child1.parentCollection);
		assertNotNull("child2Collection", child1.child1Collection);
		assertEquals("child2Collection.size()", 3, child1.child1Collection.size());		
	}
	

	
	private final static XStream setupSerializer()
	{
		final XStream s = new XStream
		(
			new PureJavaReflectionProvider(), new DomDriver()	
		);

		// Parent
		s.alias("parent", Parent.class);
		s.addImplicitCollection(Parent.class, "parentCollection", I.class);
		
		// Child1
		s.alias("child1", Child1.class);
		s.addImplicitCollection(Child1.class, "child1Collection", I.class);
		
		// Child2
		s.alias("child2", Child2.class);
		s.addImplicitCollection(Child2.class, "child2Collection", I.class);

		// IImpl1
		s.alias("i1", IImpl1.class);

		// IImpl2
		s.alias("i2", IImpl2.class);
		
		return s;
	}
}


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to