Spring Boot batch - reading XML input - convert elements to list

12,718

Solution 1

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.

Solution 2

rename this property:

private List<Child> children;

to

private List<Child> child;

and recreate the getter and setter methods.

Share:
12,718
Eria
Author by

Eria

Updated on June 04, 2022

Comments

  • Eria
    Eria almost 2 years

    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 ?