1
votes

I'm using Apache Camel to consume some XML files.
The problem is when it processes the file's attribute the values are always null...
I wrote some unit tests to be sur my XML file is valid but Camel still goes wrong...

Here is my route:

Namespaces ns = new Namespaces("ns", "http://www.vaudoise.ch/b2b/gm/interchange");
    from(source).marshal().string("ISO-8859-1").log("body = ${body}")
    .setHeader("fileName").simple("${header.CamelFileRelativePath}")
    .setHeader("lotId").xpath("//ns:documents//@T_demandeLotID", String.class, ns)
    .setHeader("typeDoc").xpath("//ns:documents//@T_demandeTypeDoc", String.class, ns)
    .setHeader("source").xpath("//ns:documents//@T_demandeSource", String.class, ns)
    .setHeader("time").xpath("//ns:documents//@T_demandeTimestamp", String.class, ns)
    .split().xpath("//ns:documents/ns:document",ns).log(" splited body  = ${body}")
    .unmarshal(new XStreamDataFormat(FichierService.getOrCreateXStream())).log("body after unmarshal ${body}")
    .transform(method(event)).to(BATCHCORE_INJECTOR);

FichierService.getOrCreateXStream() return an XStream instance like this:

  public static XStream getOrCreateXStream() {
    if (XSTREAM == null) {
      QNameMap qname = new QNameMap();
      qname.setDefaultNamespace(XMLNS);
      XmlFriendlyNameCoder replacer = new XmlFriendlyNameCoder("-", "_");
      StaxDriver staxDriver = new StaxDriver(qname, replacer);
      XSTREAM = new XStream(staxDriver);
      XSTREAM.processAnnotations(new Class[] { DocumentEnteteDto.class, 
                                                DocumentDto.class, 
                                                ReferenceDto.class,
                                                ObjetMetierDto.class, 
                                                ObjetMetierSinistreDto.class,
                                                ObjetMetierAnnonceDto.class,
                                                ObjetMetierContratDto.class,
                                                ObjetMetierFactureDto.class,
                                                ObjetMetierMutationDto.class});
      XSTREAM.registerConverter(new DateConverter("yyyy-MM-dd'T'HH:mm:ss", new String[] { "yyyy-MM-dd",
          "yyyy-MM-dd'T'HH:mm:ss" }));
      XSTREAM.registerConverter(new JodaDateConverter());
      XSTREAM.registerConverter(BooleanConverter.BINARY);
    }
    return XSTREAM;
  }

When I go step by step in the XStream classes, I see that the instruction Object value = converter.fromString(reader.getAttribute(attrAlias)); from the method doUnmarshall from the class AbstractReflectionConverter always return null

Here is an example of my XML file to consume:

<?xml version='1.0' encoding='ISO-8859-1'?>
<documents xmlns="http://www.xxx.yyy/b2b/gm/interchange" 
        T_demandeLotID="2" 
        T_demandeTypeDoc="Sinistre" 
        T_demandeSource="ST_PROG" 
        T_demandeTimestamp="2015-02-13T07:23:23">

        <document>
            <references 
                D_refSequence="132" 
                D_refContratVA="001213456.3100" 
                D_refPreneurVA="00123456" 
                D_refSinistreVA="1000012345" 
                D_refContratGM="123-GA-456" 
                D_refPreneurGM="123456" 
                D_refSinistreGM="12345678"/>

            <objetMetier>
                <sinistre 
                    S_sinistreEtat="S" 
                    S_sinistreAcceptation="1" 
                    S_sinistreDateSurv="2015-02-01" 
                    S_sinistreDevise="CHF" 
                    S_sinistreDescriptif="Vol d'un velo" 
                    S_sinistreDateLiquidation="2015-01-01">

                    <gestionnaire 
                        S_gestionnaireNom="nom" 
                        S_gestionnairePrenom="prenom" 
                        S_gestionnaireTel="tel" 
                        S_gestionnaireEmail="mail"/>
                </sinistre>
            </objetMetier>
        </document>
    </documents>
1

1 Answers

0
votes

I found my problem!

It was because of the _ in the attribute names... XStream use them as escape characters... I don't know why there were good in my unit tests but not with Camel.
To resolve the problem, I had to create two kind of instance XStream. One to marshall and one to unmarshall with a different kind of XmlFriendlyNameCoder:

 public static XStream getOrCreateXStreamToUnmarshall(){
    if(XSTREAM_TO_UNMARSHALL != null){
      return XSTREAM_TO_UNMARSHALL;
    }
    XmlFriendlyNameCoder replacer = new XmlFriendlyNameCoder("-", "");
    return createXStream(XSTREAM_TO_UNMARSHALL, replacer);
  }

  public static XStream getOrCreateXStreamToMarshall() {
    if(XSTREAM_TO_MARSHALL != null){
      return XSTREAM_TO_MARSHALL;
    }
    XmlFriendlyNameCoder replacer = new XmlFriendlyNameCoder("-", "_");
    return createXStream(XSTREAM_TO_MARSHALL, replacer);
  }

  private static XStream createXStream(XStream xSTreamToInitialize, XmlFriendlyNameCoder encoder){
    QNameMap qname = new QNameMap();
    qname.setDefaultNamespace(XMLNS_VAUDOISE);
    StaxDriver staxDriver = new StaxDriver(qname, encoder);
    xSTreamToInitialize = new XStream(staxDriver);
    xSTreamToInitialize.processAnnotations(new Class[] { DocumentEnteteDto.class, 
      DocumentDto.class, 
      ReferenceDto.class,
      ObjetMetierDto.class, 
      ObjetMetierSinistreDto.class,
      ObjetMetierAnnonceDto.class,
      ObjetMetierContratDto.class,
      ObjetMetierFactureDto.class,
      ObjetMetierMutationDto.class});
    xSTreamToInitialize.registerConverter(new DateConverter("yyyy-MM-dd'T'HH:mm:ss", new String[] { "yyyy-MM-dd",
    "yyyy-MM-dd'T'HH:mm:ss" }));
    xSTreamToInitialize.registerConverter(new JodaDateConverter());
    xSTreamToInitialize.registerConverter(BooleanConverter.BINARY);
    return xSTreamToInitialize;
  }