Search code examples
spring-bootapache-camelunmarshallingjackson-dataformat-xml

Unable to unmarshal XML using Camel JacksonXML


I'm trying to simply unmarshal an XML file as below:

<?xml version="1.0" encoding = "UTF-8" ?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <products>
        <product>
            <facet type="string" elementType="string" name="Weight (g)"><![CDATA[210]]></facet>
        </product>
    </products>
</feed>

I've got this classes:

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlRootElement(name = "feed")
@XmlAccessorType(XmlAccessType.FIELD)
public class Feed {
    private Products products;
}

Subclass Products:

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Products {
    private List<Product> products;
}

Subclass Product:

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Product {

    @XmlElement(name = "facet")
    private List<Facet> facet;
}

And finally Facet:

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Facet {
    @XmlElement(name = "name")
    private String name;

    @XmlElement(name = "type")
    private String type;

    @XmlElement(name = "elementType")
    private String elementType;

    private String content;
}

The camel route I've written to unmarshall is as below:

@Component
public class XMLSplitterRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        from("file:src/main/resources/files/xml").routeId("xmlUmarshaller")
            .log("body: ${body}")
            .unmarshal().jacksonXml(Products.class)
                .log("The unmarshalled object is ${body}")
            .marshal().json()
            .to("activemq:json-marshal-queue");
    }
}

But I keep getting the error below:

com.fasterxml.jackson.databind.JsonMappingException: Unexpected non-whitespace text ('210' in Array context: should not occur (or should be handled)
 at [Source: (BufferedInputStream); line: 29, column: 96] (through reference chain: com.sammy.model.Products["products"]->java.util.ArrayList[0]->com.sammy.model.Product["facet"])

and

Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected non-whitespace text ('210' in Array context: should not occur (or should be handled)
 at [Source: (BufferedInputStream); line: 29, column: 96]

This means, it seems not to know what to do with the value within the cdata of the XML file! I've looked everywhere but not seen any potential solution. Please, help!!!


Solution

  • From the nice suggestiongs of Nicolas Filotto, I fixed my mappings by first converting my XML to XSD then generated the POJO's using xjc. For Camel unmarshal process, I changed it from jacksonXML to use Jaxb converter.

    @Component
    public class XMLSplitterRoute extends RouteBuilder {
    
        @Override
        public void configure() throws Exception {
    
            DataFormat jaxb = new JaxbDataFormat("com.sammy.model");
    
            from("file:src/main/resources/files/xml").routeId("xmlSplitter")
                .log("body: ${body}")
                .unmarshal(jaxb)
                    .log("The unmarshalled object is ${body}")
        }
    }
    

    This now works like a charm!!!