Reputation: 3182
I have to code a batch service, using Spring Boot, that reads an XML file as input. The structure of the XML input looks like this, and I can't change it :
<root>
<parent>
<field1>string</field1>
<field2>string</field2>
<field3>string</field2>
<child>
<fieldA>string</fieldA>
<fieldB>string</fieldB>
</child>
<child>
<fieldA>string</fieldA>
<fieldB>string</fieldB>
</child>
<child>
<fieldA>string</fieldA>
<fieldB>string</fieldB>
</child>
</parent>
</root>
I've created my Java classes :
public class Parent {
private String field1;
private String field2;
private String field3;
private List<Child> children;
// Getters and setters...
}
public class Child {
private String fieldA;
private String fieldB;
// Getters and setters...
}
And here is my reader in the batch configuration class :
@Bean
public ItemReader<Object> reader(){
StaxEventItemReader<Object> reader = new StaxEventItemReader<Object>();
reader.setResource( new ClassPathResource("input.xml") );
reader.setFragmentRootElementName("parent");
XStreamMarshaller unmarshaller = new XStreamMarshaller();
Map<String, Class> aliases = new HashMap<String, Class>();
aliases.put( "parent", Parent.class );
aliases.put( "child", Child.class );
unmarshaller.setAliases(aliases);
reader.setUnmarshaller( unmarshaller );
return reader;
}
For now I just try to have a correct reading. But when I run the batch, I have an error :
org.springframework.oxm.UnmarshallingFailureException: XStream unmarshalling exception; nested exception is com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field foo.bar.Parent.child
I understand this error, but I can't find a way to correct my code. I tried to create a fake setter in Parent, adding the child to the children list. But it doesn't seem to work.
Any idea ?
Upvotes: 2
Views: 13628
Reputation: 3182
I solved the problem using Jaxb2Marshaller instead of XStreamMarshaller :
@Bean
public ItemReader<Object> reader(){
StaxEventItemReader<Object> reader = new StaxEventItemReader<Object>();
reader.setResource( new ClassPathResource("input.xml") );
reader.setFragmentRootElementName("parent");
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setClassesToBeBound( Parent.class, Child.class );
reader.setUnmarshaller( unmarshaller );
return reader;
}
And for Java beans :
@XmlRootElement(name = "parent")
public class Parent {
private String field1;
private String field2;
private String field3;
private List<Child> child;
// Getters and setters...
}
public class Child {
private String fieldA;
private String fieldB;
// Getters and setters...
}
This works fine, even with the auto-generated getters and setters : I recover a list of the children elements.
Upvotes: 5
Reputation: 69440
rename this property:
private List<Child> children;
to
private List<Child> child;
and recreate the getter and setter methods.
Upvotes: 2