Question

I'm observing really weird behavior from the XStream library while reading the file it generated and using Patter.compile on the results When ran it gives null pointer exception but it works fine if I run it step by step in a debug mode.
I'v narrowed it down to Pattern.complie If I just reads value to a string variable it works fine, if I use Pattern.complie(".*") withing the unmarshal method it works fine too
I use Java 7 and XStream 1.4.4
I think this is due reader.getAttribute("key") returning null but not when debugging Any idea why is this happning ?
Here is what I have:
My class

import java.util.regex.Pattern;
public class A {
private Pattern key;
ArrayList<A> subTree;
public A(HierarchicalStreamReader reader, UnmarshallingContext context){
    this.key=Pattern.compile(reader.getAttribute("key"));
            // String a = reader.getAttribute("key") - Works fine
            // this.key=Pattern.compile(a) - Breaks   
    subTree=new ArrayList<A>();
    reader.moveDown();
    while(reader.hasMoreChildren()) {
        subTree.add(new A(reader,context));
    }
    reader.moveUp();
}
}

XStream converter class

public class AConverter implements Converter {
    public boolean canConvert(Class clazz) {
        return A.class.isAssignableFrom(clazz);
    }

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {

    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        reader.moveDown();
        A n = new A(reader,context);
        reader.moveUp();
        return n;
    }

}

Test case

public void testA() throws FileNotFoundException, IOException, ClassNotFoundException{
    XStream xstream = new XStream();
    xstream.alias("MessageFieldMappings", A.class);
    xstream.registerConverter(new AConverter());
    ObjectInputStream in = xstream.createObjectInputStream(new FileInputStream("test1.xml"));
    A rootNode = (A) in.readObject();
    in.close();

}

Test file (test1.xml)

<object-stream>
<MessageFieldMappings>
<RootMapping>
  <FieldMap key=".*">
    <FieldMap key="A.*">
      <FieldMap key="AB.*"/>
      <FieldMap key="AC.*"/>
    </FieldMap>
    <FieldMap key="D.*"/>
  </FieldMap>
</RootMapping>
</MessageFieldMappings>
</object-stream>

The error I get

com.thoughtworks.xstream.converters.ConversionException: null : null
---- Debugging information ----
cause-exception     : java.lang.NullPointerException
cause-message       : null
class               : nz.orion.monkPraser.praser.fieldConverter.A
required-type       : nz.orion.monkPraser.praser.fieldConverter.A
converter-type      : nz.orion.monkPraser.praser.fieldConverter.AConverter
path                : /MessageFieldMappings/RootMapping
line number         : 3
version             : null
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79)
...
Was it helpful?

Solution

The clue is in

path                : /MessageFieldMappings/RootMapping
line number         : 3

You've aliased MessageFieldMappings to class A, so when it sees a MessageFieldMappings it will call the converter, which will moveDown to the RootMapping element and attempt to extract a key attribute from that. It doesn't have one, hence the NPE.

You need an extra level of moveDown/Up in the converter:

reader.moveDown(); // RootMapping
reader.moveDown(); // First FieldMap
A n = new A(reader,context);
reader.moveUp();
reader.moveUp();
return n;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top