2015-10-09 6 views
2

Je dois coder un service de traitement par lots, en utilisant Spring Boot, qui lit un fichier XML en entrée. La structure de l'entrée XML ressemble à ceci, et je ne peux pas changer:Spring Boot - lecture de l'entrée XML - conversion des éléments en liste

<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> 

J'ai créé mes classes Java:

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... 
} 

Et voici mon lecteur dans la configuration par lots 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; 
} 

Pour l'instant j'essaie juste d'avoir une lecture correcte. Mais quand je lance le lot, j'ai une erreur:

org.springframework.oxm.UnmarshallingFailureException: XStream unmarshalling exception; nested exception is com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field foo.bar.Parent.child 

Je comprends cette erreur, mais je ne peux pas trouver un moyen de corriger mon code. J'ai essayé de créer un faux setter dans Parent, en ajoutant l'enfant à la liste des enfants. Mais cela ne semble pas fonctionner.

Toute idée?

Répondre

5

Je résolu le problème en utilisant Jaxb2Marshaller au lieu de 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; 
} 

Et pour Java haricots:

@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... 
} 

Cela fonctionne très bien, même avec les apporteurs générés automatiquement et setters: Je récupère un liste des éléments enfants.

+0

Merci. Jaxb2Marshaller a sauvé ma journée –

+0

De rien! Cela m'a sauvé des heures aussi. – Eria

2

renommage cette propriété:

private List<Child> children; 

à

private List<Child> child; 

et de recréer les méthodes getter et setter.

+0

Que dois-je mettre dans la méthode getter? Si je retourne la liste, le batch essaie alors d'appeler setFieldA() sur une liste, et échoue. – Eria