History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XSTR-335
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Assignee: Joerg Schaible
Reporter: joerg
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
XStream

Aliases/Annotations for Fields of Baseclasses are not handled correctly

Created: 24/Aug/06 07:00 AM   Updated: 25/Feb/08 05:01 PM
Component/s: None
Affects Version/s: None
Fix Version/s: 1.3

File Attachments: 1. File xstream-test.tgz (2 kb)

Issue Links:
Related
 

JDK version and platform: JDK 1.5, Linux


 Description  « Hide
When I have a baseclass with field annotations or I want to set the aliases by hand, the toXML method is working correctly with the derived class (taking the alias into account) but the fromXML method throws an exception.

Somehow, he's missing the information about the alias information of the fields of the base class and tries to load the element name as a class.

Example (with alias):

public class XTestBaseAlias {

String baseName;

public XTestBaseAlias( String baseName) {
this.baseName= baseName;
}
}

public class XStreamTestAlias extends XTestBaseAlias {

String name;
int y;

public XStreamTestAlias( String baseName, String name, int y) {
super( baseName);
this.name= name;
this.y= y;
}

public String toString() {
return "XStreamTest::name="+name+" y="+y;
}

public static void main( String[] argv) {
XStream xstream= new XStream( new DomDriver());
xstream.alias( "test-annotation", XStreamTestAlias.class);
xstream.aliasField( "alias-name", XStreamTestAlias.class, "name");
xstream.aliasField( "alias-y", XStreamTestAlias.class, "y");

               // note: the base class is used here for the field alias
               // otherwise the alias is not taken into account at all (also in toXML() )
xstream.aliasField( "alias-base-name", XTestBaseAlias.class, "baseName");

XStreamTestAlias test= new XStreamTestAlias( "base1", "t1", 3);

String str= xstream.toXML( test);

System.out.println( str);
System.out.println( "\n-------------------------\n");

XStreamTestAlias test1= (XStreamTestAlias)xstream.fromXML( str);

System.out.println( test1);
}
}

When you run the main method you will get the following output:

<test-annotation>
  <alias-name>t1</alias-name>
  <alias-y>3</alias-y>
  <alias-base-name>base1</alias-base-name>
</test-annotation>

-------------------------

Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: alias$base$name : alias$base$name
---- Debugging information ----
required-type : com.freiheit.test.XStreamTestAlias
cause-message : alias$base$name : alias$base$name
class : com.freiheit.test.XStreamTestAlias
message : alias$base$name : alias$base$name
path : /test-annotation/alias-base-name
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:63)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:45)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:46)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:117)
at com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy.unmarshal(ReferenceByXPathMarshallingStrategy.java:29)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:826)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:813)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:761)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:753)
at com.freiheit.test.XStreamTestAlias.main(XStreamTestAlias.java:46)
Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: alias$base$name : alias$base$name
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:49)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper.realClass(XStream11XmlFriendlyMapper.java:23)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:72)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:60)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:76)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:26)
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:34)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:254)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:155)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:118)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:56)
... 9 more

The sources and testcases are in the attached tgz file together with a similar example with annotations.


 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
joerg - 31/Aug/06 11:42 AM
Because this bug prevents me from using XStream in a project, where I would very much like to have it used, I downloaded the sources of Version 1.2 and figured out the call stack a little bit.
I made the following, naive patch to the realMember() method of the FieldAliasingMapper class which solved the problem for me:

    public String realMember(Class type, String serialized) {
        Class tt= type;
        String real = null;
        while( real == null && ! tt.equals( Object.class)) {
            real = (String) aliasToFieldMap.get(key( tt, serialized));
            if( real == null) tt= tt.getSuperclass();
        }
        if (real == null) {
            return super.realMember(type, serialized);
        } else {
            return real;
        }
    }


Joerg Schaible - 23/Nov/07 05:33 PM - edited
Annotation inheritance works in the current head revision, you may give it a try. All your provided tests run on this version without any problem.

Joerg Schaible - 25/Feb/08 05:01 PM
Closing issues before next release.