The rise of SOAP and REST web services a few years ago required robust solutions for serializing and deserializing the data. Mapping of XML documents into corresponding Java classes became crucial. A variety of libraries were created that provided the ability to marshal Java objects into XML and unmarshal XML back to Java without the need to implement a custom code. One of them was JAXB – Java Architecture for XML Binding, currently Jakarta XML Binding (https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html).

JAXB

In JAXB, mapping between XML and Java objects is realized with annotations added to the Java classes definition.

               @XmlAccessorType(XmlAccessType.FIELD)

               @XmlType(name = “CarData”, namespace = https://com.sabre/car, propOrder = {

                   “carCompany”,

                   “carType”,

                   “supplementalInfo”

               })

               @XmlRootElement(name = “CarData”, namespace = https://com.sabre/car)

               public class CarData {

                   @XmlElement(name = “CarCompany”)

                   protected String carCompany;

                   @XmlElement(name = “CarType”)

                   protected String carType;

                   @XmlElement(name = “SupplementalInfo”)

                   protected String supplementalInfo;

                    …   

               }

Annotations determine JAXB processing. Customization is optional, nevertheless, in practice, it is necessary to use them e.g. to define XML namespaces or serialized field names.

Classes can be written by hand or generated from .xsd files. JAXB provides a binding compiler – XJC – which generates annotated classes based on .xsd schema files.

               .xsd -> annotated classes

JAXB to perform marshalling and unmarshaling needs a context. Context creation involves listing, loading and instantiating all classes that can be used during the marshalling and unmarshalling process.

               list of classes or packages -> JAXB context

The time required for context creation is correlated with the number of classes in the context. Building extensive context may significantly impact application startup time.

JAXB can handle large-size XML documents, up to several MB (tested with ~50MB documents), nevertheless, the processing is memory-consuming and may lead to out-of-memory exceptions.

JAXB is a comprehensive tool, but not free of limitations, some may be unacceptable for specific types of applications. JAXB is a part of Java since Java 6. In Java 9, due to modularization of the JDK and increased interest in JSON services, it was marked as deprecated. In Java 11 JAXB was completely removed and to use it JAXB API and JAXB implementation must be added separately, e.g. as a Maven dependency.

JAXB originally was designed to handle XMLs, to work with JSONs it is required to use one of its implementations – MOXy.

<dependencies>

<dependency>

<groupId>org.eclipse.persistence</groupId>

<artifactId>org.eclipse.persistence.moxy</artifactId>

<version>…</version>

</dependency>

<dependency>

<groupId>javax.xml.bind</groupId>

<artifactId>jaxb-api</artifactId>

<version>…</version>

</dependency>

</dependencies>

Are there any alternatives for JAXB?

Many libraries can help with XML and JSON marshalling and unmarshaling. The most known and popular libraries are: DOM4J, JDOM, StAX API (included in the JDK since Java 6), XStream, JiBX and Jackson. Each of them has its requirements and limitations and can efficiently handle different XML or JSON documents. Some of them are intended to be used with simple documents, while others provide more features, like namespaces or advanced mapping customization.

The problem is if you already have an application that uses JAXB and you would like to replace it with a different one. XMLs and JSONs produced by different tools are valid but may differ in their structure. The main differences are in handling collections. JAXB provides several optimizations that on one hand make the XML and JSON documents simpler – like single element collections which are treated as a regular field or a string collection that are serialized as a space-separated list of items – but on the other hand, make the same XML or JSON documents not compatible with those created by other tools.

This simple class below

class SimpleStringList {

   @XmlList

   @XmlElement

   private List <String> list; 

}

is serialized to JSON by Jackson to:

{“list”:[“aaa”,”bbb”,”ccc”]}

but JAXB serializes it to:

{“list”:”aaa bbb ccc”}

Jackson

Jackson is a very popular high-performance Java library for processing JSONs. It provides data-binding functionality that can be used to convert Java objects into their JSON representation and vice versa.

While JSON is Jackson’s core competency, it comes with a number of optional modules that provide support for e.g.: XML, YAML or CSV formats.

With XML module Jackson provides support for JAXB (javax.xml.bind) annotations as an alternative to native Jackson annotations, so it is possible to reuse existing data beans that are created with JAXB to read and write XMLs.

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.13.0</version>

</dependency>

The XML module in Jackson was not designed to be an exact replacement for JAXB. Certain constructs work differently, there is no guarantee that Jackson will produce identical XML to JAXBJackson has also no support for advanced XML features that can be easily handled by JAXB. Different handling of collections and arrays, lack of support for XML references and lack of support for elements marked with @XmlAnyELement or @XmlAnyttribute are key differences.

All these limitations make it impossible to use Jackson as a JAXB replacement out of the box, except for very primitive schemas. Nevertheless, Jackson flexible architecture creates a possibility to modify its behavior at almost any point of the marshalling and unmarshaling process. Jackson allows injecting custom serializers, deserializers, modifiers, property writers or annotation introspectors to alter default behavior. Modification of the default logic opens the possibility to make Jackson produce and accept exactly the same XML and JSON documents as JAXB.

Is it possible?

Sabre Red 360 (SR360) is the travel agencies’ access point to the content of the Sabre services. It is built on APIs to seamlessly integrate a spectrum of bookable content and data-rich information. Consuming dozens of SOAP and REST services, SR360 processes huge amounts of different data that must be serialized and deserialized from JSON or XML.

SR360 successfully migrated from JAXB to Jackson without a single line of code change in the application. By extending Jackson framework with custom logic it was possible to make Jackson handle the same JSONs and XMLs as JAXB, making the change completely transparent. The application now starts much faster as creating the context for Jackson doesn’t require as much time as for JAXB. Occasional out-of-memory errors during large XML processing were also eliminated and Jackson can handle even larger XML documents with the same amount of available memory.

Pawel Antoniewski is a part of Sabre’s Travel Solutions team for over 16 years. A Java expert and one of the first developers in SabreRed360 project, he serves as a Principal – Software Engineer, leading and driving technical initiatives that improves the stability and performance of the application.