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)
...
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;