JAXB
Since Camel 1.0
JAXB is a Data Format which uses the JAXB2 XML marshalling standard which is included in Java 6 to unmarshal an XML payload into Java objects or to marshal Java objects into an XML payload.
Options
The JAXB dataformat supports 18 options, which are listed below.
Name | Default | Java Type | Description |
---|---|---|---|
contextPath |
|
Package name where your JAXB classes are located. |
|
schema |
|
To validate against an existing schema. Your can use the prefix classpath:, file: or http: to specify how the resource should by resolved. You can separate multiple schema files by using the ',' character. |
|
schemaSeverityLevel |
|
|
Sets the schema severity level to use when validating against a schema. This level determines the minimum severity error that triggers JAXB to stop continue parsing. The default value of 0 (warning) means that any error (warning, error or fatal error) will trigger JAXB to stop. There are the following three levels: 0=warning, 1=error, 2=fatal error. The value can be one of: 0, 1, 2 |
prettyPrint |
|
|
To enable pretty printing output nicely formatted. Is by default false. |
objectFactory |
|
|
Whether to allow using ObjectFactory classes to create the POJO classes during marshalling. This only applies to POJO classes that has not been annotated with JAXB and providing jaxb.index descriptor files. |
ignoreJAXBElement |
|
|
Whether to ignore JAXBElement elements - only needed to be set to false in very special use-cases. |
mustBeJAXBElement |
|
|
Whether marhsalling must be java objects with JAXB annotations. And if not then it fails. This option can be set to false to relax that, such as when the data is already in XML format. |
filterNonXmlChars |
|
|
To ignore non xml characheters and replace them with an empty space. |
encoding |
|
To overrule and use a specific encoding |
|
fragment |
|
|
To turn on marshalling XML fragment trees. By default JAXB looks for XmlRootElement annotation on given class to operate on whole XML tree. This is useful but not always - sometimes generated code does not have XmlRootElement annotation, sometimes you need unmarshall only part of tree. In that case you can use partial unmarshalling. To enable this behaviours you need set property partClass. Camel will pass this class to JAXB’s unmarshaler. |
partClass |
|
Name of class used for fragment parsing. See more details at the fragment option. |
|
partNamespace |
|
XML namespace to use for fragment parsing. See more details at the fragment option. |
|
namespacePrefixRef |
|
When marshalling using JAXB or SOAP then the JAXB implementation will automatic assign namespace prefixes, such as ns2, ns3, ns4 etc. To control this mapping, Camel allows you to refer to a map which contains the desired mapping. |
|
xmlStreamWriterWrapper |
|
To use a custom xml stream writer. |
|
schemaLocation |
|
To define the location of the schema |
|
noNamespaceSchemaLocation |
|
To define the location of the namespaceless schema |
|
jaxbProviderProperties |
|
Refers to a custom java.util.Map to lookup in the registry containing custom JAXB provider properties to be used with the JAXB marshaller. |
|
contentTypeHeader |
|
|
Whether the data format should set the Content-Type header with the type from the data format if the data format is capable of doing so. For example application/xml for data formats marshalling to XML, or application/json for data formats marshalling to JSon etc. |
Using the Java DSL
For example the following uses a named DataFormat of jaxb which is configured with a number of Java package names to initialize the JAXBContext.
DataFormat jaxb = new JaxbDataFormat("com.acme.model");
from("activemq:My.Queue").
unmarshal(jaxb).
to("mqseries:Another.Queue");
You can if you prefer use a named reference to a data format which can then be defined in your Registry such as via your Spring XML file. e.g.
from("activemq:My.Queue").
unmarshal("myJaxbDataType").
to("mqseries:Another.Queue");
Using Spring XML
The following example shows how to use JAXB to unmarshal using Spring configuring the jaxb data type
This example shows how to configure the data type just once and reuse it on multiple routes.
Multiple context paths
It is possible to use this data format with more than one context path.
You can specify context path using :
as separator, for example
com.mycompany:com.mycompany2
. Note that this is handled by JAXB
implementation and might change if you use different vendor than RI.
Partial marshalling/unmarshalling
JAXB 2 supports marshalling and unmarshalling XML tree fragments. By default JAXB looks for `@XmlRootElement` annotation on given class to operate on whole XML tree. This is useful but not always - sometimes generated code does not have @XmlRootElement annotation, sometimes you need unmarshall only part of tree. + In that case you can use partial unmarshalling. To enable this behaviours you need set property `partClass`. Camel will pass this class to JAXB's unmarshaler. If `JaxbConstants.JAXB_PART_CLASS` is set as one of headers, (even if partClass property is set on DataFormat), the property on DataFormat is surpassed and the one set in the headers is used.
For marshalling you have to add partNamespace
attribute with QName of
destination namespace. Example of Spring DSL you can find above.
If JaxbConstants.JAXB_PART_NAMESPACE
is set as
one of headers, (even if partNamespace property is set on DataFormat), the property
on DataFormat is surpassed and the one set in the headers is used. While setting
partNamespace
through JaxbConstants.JAXB_PART_NAMESPACE
, please
note that you need to specify its value {[namespaceUri]}[localPart]
...
.setHeader(JaxbConstants.JAXB_PART_NAMESPACE, simple("{http://www.camel.apache.org/jaxb/example/address/1}address"));
...
Fragment
JaxbDataFormat has new property fragment which can set the the `Marshaller.JAXB_FRAGMENT` encoding property on the JAXB Marshaller. If you don't want the JAXB Marshaller to generate the XML declaration, you can set this option to be true. The default value of this property is false.
Ignoring the NonXML Character
JaxbDataFormat supports to ignore the http://www.w3.org/TR/2004/REC-xml-20040204/#NT-Char[NonXML Character], you just need to set the filterNonXmlChars property to be true, JaxbDataFormat will replace the NonXML character with " " when it is marshaling or unmarshaling the message. You can also do it by setting the Exchange property `Exchange.FILTER_NON_XML_CHARS`.
JDK 1.5 | JDK 1.6+ | |
---|---|---|
Filtering in use |
StAX API and implementation |
No |
Filtering not in use |
StAX API only |
No |
This feature has been tested with Woodstox 3.2.9 and Sun JDK 1.6 StAX implementation.
JaxbDataFormat now allows you to customize the XMLStreamWriter used to marshal the stream to XML. Using this configuration, you can add your own stream writer to completely remove, escape, or replace non-xml characters.
JaxbDataFormat customWriterFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
customWriterFormat.setXmlStreamWriterWrapper(new TestXmlStreamWriter());
The following example shows using the Spring DSL and also enabling Camel’s NonXML filtering:
<bean id="testXmlStreamWriterWrapper" class="org.apache.camel.jaxb.TestXmlStreamWriter"/>
<jaxb filterNonXmlChars="true" contextPath="org.apache.camel.foo.bar" xmlStreamWriterWrapper="#testXmlStreamWriterWrapper" />
Working with the ObjectFactory
If you use XJC to create the java class from the schema, you will get an
ObjectFactory for you JAXB context. Since the ObjectFactory uses
JAXBElement
to hold the reference of the schema and element instance value,
jaxbDataformat will ignore the JAXBElement by default and you will get
the element instance value instead of the JAXBElement object form the
unmarshaled message body.
If you want to get the JAXBElement object form the unmarshaled message
body, you need to set the JaxbDataFormat object’s ignoreJAXBElement
property to be false.
Setting encoding
You can set the encoding option to use when marshalling. Its the
Marshaller.JAXB_ENCODING
encoding property on the JAXB Marshaller.
You can setup which encoding to use when you declare the JAXB data
format. You can also provide the encoding in the
Exchange property Exchange.CHARSET_NAME
. This
property will overrule the encoding set on the JAXB data format.
In this Spring DSL we have defined to use iso-8859-1
as the encoding:
Controlling namespace prefix mapping
Since Camel 2.11
When marshalling using JAXB or SOAP then the JAXB implementation will automatic assign namespace prefixes, such as ns2, ns3, ns4 etc. To control this mapping, Camel allows you to refer to a map which contains the desired mapping.
Notice this requires having JAXB-RI 2.1 or better (from SUN) on the classpath, as the mapping functionality is dependent on the implementation of JAXB, whether its supported.
For example in Spring XML we can define a Map with the mapping. In the mapping file below, we map SOAP to use soap as prefix. While our custom namespace "http://www.mycompany.com/foo/2" is not using any prefix.
<util:map id="myMap">
<entry key="http://www.w3.org/2003/05/soap-envelope" value="soap"/>
<!-- we dont want any prefix for our namespace -->
<entry key="http://www.mycompany.com/foo/2" value=""/>
</util:map>
To use this in JAXB or SOAP you refer to
this map, using the namespacePrefixRef
attribute as shown below. Then
Camel will lookup in the Registry a java.util.Map
with the id "myMap", which was what we defined above.
<marshal>
<soapjaxb version="1.2" contextPath="com.mycompany.foo" namespacePrefixRef="myMap"/>
</marshal>
Schema validation
Since Camel 2.11
The JAXB Data Format supports validation by marshalling and unmarshalling from/to XML. Your can use the prefix classpath:, file: or http: to specify how the resource should by resolved. You can separate multiple schema files by using the ',' character.
Using the Java DSL, you can configure it in the following way:
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setContextPath(Person.class.getPackage().getName());
jaxbDataFormat.setSchema("classpath:person.xsd,classpath:address.xsd");
You can do the same using the XML DSL:
<marshal>
<jaxb id="jaxb" schema="classpath:person.xsd,classpath:address.xsd"/>
</marshal>
Camel will create and pool the underling SchemaFactory
instances on
the fly, because the SchemaFactory
shipped with the JDK is not thread
safe.
However, if you have a SchemaFactory
implementation which is thread
safe, you can configure the JAXB data format to use this one:
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setSchemaFactory(thradSafeSchemaFactory);
Schema Location
Since Camel 2.14
The JAXB Data Format supports to specify the SchemaLocation when marshaling the XML.
Using the Java DSL, you can configure it in the following way:
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setContextPath(Person.class.getPackage().getName());
jaxbDataFormat.setSchemaLocation("schema/person.xsd");
You can do the same using the XML DSL:
<marshal>
<jaxb id="jaxb" schemaLocation="schema/person.xsd"/>
</marshal>
Marshal data that is already XML
Since Camel 2.14.1
The JAXB marshaller requires that the message body is JAXB compatible,
eg its a JAXBElement, eg a java instance that has JAXB annotations, or
extend JAXBElement. There can be situations where the message body is
already in XML, eg from a String type. There is a new
option mustBeJAXBElement
you can set to false, to relax this check, so
the JAXB marshaller only attempts to marshal JAXBElements
(javax.xml.bind.JAXBIntrospector#isElement returns true). And in those
situations the marshaller fallbacks to marshal the message body as-is.
Dependencies
To use JAXB in your camel routes you need to add the a dependency on camel-jaxb which implements this data format.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jaxb</artifactId>
<version>x.x.x</version>
</dependency>
Spring Boot Auto-Configuration
When using jaxb with Spring Boot make sure to use the following Maven dependency to have support for auto configuration:
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jaxb-starter</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
The component supports 20 options, which are listed below.
Name | Description | Default | Type |
---|---|---|---|
camel.dataformat.jaxb.content-type-header |
Whether the data format should set the Content-Type header with the type from the data format if the data format is capable of doing so. For example application/xml for data formats marshalling to XML, or application/json for data formats marshalling to JSON etc. |
false |
Boolean |
camel.dataformat.jaxb.context-path |
Package name where your JAXB classes are located. |
String |
|
camel.dataformat.jaxb.context-path-is-class-name |
This can be set to true to mark that the contextPath is referring to a classname and not a package name. |
false |
Boolean |
camel.dataformat.jaxb.enabled |
Whether to enable auto configuration of the jaxb data format. This is enabled by default. |
Boolean |
|
camel.dataformat.jaxb.encoding |
To overrule and use a specific encoding |
String |
|
camel.dataformat.jaxb.filter-non-xml-chars |
To ignore non xml characheters and replace them with an empty space. |
false |
Boolean |
camel.dataformat.jaxb.fragment |
To turn on marshalling XML fragment trees. By default JAXB looks for XmlRootElement annotation on given class to operate on whole XML tree. This is useful but not always - sometimes generated code does not have XmlRootElement annotation, sometimes you need unmarshall only part of tree. In that case you can use partial unmarshalling. To enable this behaviours you need set property partClass. Camel will pass this class to JAXB’s unmarshaler. |
false |
Boolean |
camel.dataformat.jaxb.ignore-j-a-x-b-element |
Whether to ignore JAXBElement elements - only needed to be set to false in very special use-cases. |
false |
Boolean |
camel.dataformat.jaxb.jaxb-provider-properties |
Refers to a custom java.util.Map to lookup in the registry containing custom JAXB provider properties to be used with the JAXB marshaller. |
String |
|
camel.dataformat.jaxb.must-be-j-a-x-b-element |
Whether marhsalling must be java objects with JAXB annotations. And if not then it fails. This option can be set to false to relax that, such as when the data is already in XML format. |
false |
Boolean |
camel.dataformat.jaxb.namespace-prefix-ref |
When marshalling using JAXB or SOAP then the JAXB implementation will automatic assign namespace prefixes, such as ns2, ns3, ns4 etc. To control this mapping, Camel allows you to refer to a map which contains the desired mapping. |
String |
|
camel.dataformat.jaxb.no-namespace-schema-location |
To define the location of the namespaceless schema |
String |
|
camel.dataformat.jaxb.object-factory |
Whether to allow using ObjectFactory classes to create the POJO classes during marshalling. This only applies to POJO classes that has not been annotated with JAXB and providing jaxb.index descriptor files. |
false |
Boolean |
camel.dataformat.jaxb.part-class |
Name of class used for fragment parsing. See more details at the fragment option. |
String |
|
camel.dataformat.jaxb.part-namespace |
XML namespace to use for fragment parsing. See more details at the fragment option. |
String |
|
camel.dataformat.jaxb.pretty-print |
To enable pretty printing output nicely formatted. Is by default false. |
false |
Boolean |
camel.dataformat.jaxb.schema |
To validate against an existing schema. Your can use the prefix classpath:, file: or http: to specify how the resource should by resolved. You can separate multiple schema files by using the ',' character. |
String |
|
camel.dataformat.jaxb.schema-location |
To define the location of the schema |
String |
|
camel.dataformat.jaxb.schema-severity-level |
Sets the schema severity level to use when validating against a schema. This level determines the minimum severity error that triggers JAXB to stop continue parsing. The default value of 0 (warning) means that any error (warning, error or fatal error) will trigger JAXB to stop. There are the following three levels: 0=warning, 1=error, 2=fatal error. |
0 |
Integer |
camel.dataformat.jaxb.xml-stream-writer-wrapper |
To use a custom xml stream writer. |
String |