I created a xsd and used it with jaxb plugin like bellow:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.mycompany.fr/Canonical/Schema/invoices.xsd"
targetNamespace="http://www.mycompany.fr/Canonical/Schema/invoices.xsd"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="invoices">
<xs:complexType>
<xs:sequence>
<xs:element name="invoice" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="invoice-type" type="xs:string"/>
<xs:element minOccurs="0" name="insertion-date" type="xs:dateTime"/>
<xs:element minOccurs="0" name="amount" type="xs:double"/>
</xs:sequence>
<xs:attribute name="invoice-number" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xsd-to-java</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>com.mycompany.model</packageName>
<sources>
<source>src/main/resources/xsd/invoices.xsd</source>
</sources>
</configuration>
</plugin>
It generated me this class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"invoice"
})
@XmlRootElement(name = "invoices")
public class Invoices {
protected List<Invoice> invoice;
/**
* Gets the value of the invoice property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the invoice property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getInvoice().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Invoice }
*
*
*/
public List<Invoice> getInvoice() {
if (invoice == null) {
invoice = new ArrayList<Invoice>();
}
return this.invoice;
}
/**
* <p>Classe Java pour anonymous complex type.
*
* <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="invoice-type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="insertion-date" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
* <element name="amount" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
* </sequence>
* <attribute name="invoice-number" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"invoiceType",
"insertionDate",
"amount"
})
public static class Invoice {
@XmlElement(name = "invoice-type")
protected String invoiceType;
@XmlElement(name = "insertion-date")
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar insertionDate;
protected Double amount;
@XmlAttribute(name = "invoice-number", required = true)
protected String invoiceNumber;
/**
* Obtient la valeur de la propriété invoiceType.
*
* @return
* possible object is
* {@link String }
*
*/
public String getInvoiceType() {
return invoiceType;
}
/**
* Définit la valeur de la propriété invoiceType.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setInvoiceType(String value) {
this.invoiceType = value;
}
/**
* Obtient la valeur de la propriété insertionDate.
*
* @return
* possible object is
* {@link XMLGregorianCalendar }
*
*/
public XMLGregorianCalendar getInsertionDate() {
return insertionDate;
}
/**
* Définit la valeur de la propriété insertionDate.
*
* @param value
* allowed object is
* {@link XMLGregorianCalendar }
*
*/
public void setInsertionDate(XMLGregorianCalendar value) {
this.insertionDate = value;
}
/**
* Obtient la valeur de la propriété amount.
*
* @return
* possible object is
* {@link Double }
*
*/
public Double getAmount() {
return amount;
}
/**
* Définit la valeur de la propriété amount.
*
* @param value
* allowed object is
* {@link Double }
*
*/
public void setAmount(Double value) {
this.amount = value;
}
/**
* Obtient la valeur de la propriété invoiceNumber.
*
* @return
* possible object is
* {@link String }
*
*/
public String getInvoiceNumber() {
return invoiceNumber;
}
/**
* Définit la valeur de la propriété invoiceNumber.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setInvoiceNumber(String value) {
this.invoiceNumber = value;
}
}
}
And I used this Camel route to unmasharl the xml:
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setSchema("classpath:xsd/invoices.xsd");
from("file:{{xml.location}}?delay=1000")
.log("Reading invoice XML data from ${header.CamelFileName}")
.unmarshal(jaxbDataFormat)
.split(body())
.to("direct:processedXml");
but when I run my application, I got the following error ...
[route2 ] [unmarshal1 ] [unmarshal[org.apache.camel.model.dataformat.JaxbDataFormat@7aff8796] ] [ 0]
Stacktrace --------------------------------------------------------------------------------------------------------------------------------------- : java.io.IOException: javax.xml.bind.UnmarshalException
- with linked exception: [com.sun.istack.SAXParseException2; lineNumber: 2; columnNumber: 72; élément inattendu (URI : "http://www.mycompany.fr/Canonical/Schema/invoices.xsd", local : "invoices"). Les éléments attendus sont (none)] at org.apache.camel.converter.jaxb.JaxbDataFormat.unmarshal(JaxbDataFormat.java:312) at org.apache.camel.support.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:64) at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:471) at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:187) at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:64) at org.apache.camel.processor.Pipeline.process(Pipeline.java:184) at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:398) at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:492) at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:245) at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:206) at org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:202) at org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:116) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: javax.xml.bind.UnmarshalException
Do you know the problem plz ?
Thank a lot and best regards
When unmarshalling, you do not need to refer to a schema, but to a JAXB contextPath
. You have to tell JAXB where (=in which packages) to find annotated pojos so that it will be able to turn xml into corresponding java objects.
So try this:
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setContextPath("com.mycompany.model");