Core Java

JAXB Is Doing It Wrong; Try Xembly

JAXB is a 10-year-old Java technology that allows us to convert a Java object into an XML document (marshalling) and back (unmarshalling). This technology is based on setters and getters and, in my opinion, violates key principles of object-oriented programming by turning objects into passive data structures. I would recommend you use Xembly instead for marshalling Java objects into XML documents.

This is how JAXB marshalling works. Say you have a Book class that needs to be marshalled into an XML document. You have to create getters and annotate them:

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  @XmlElement
  public String getIsbn() {
    return this.isbn;
  }
  @XmlElement
  public String getTitle() {
    return this.title;
  }
}

Then you create a marshaller and ask it to convert an instance of class Book into XML:

final Book book = new Book("0132350882", "Clean Code");
final JAXBContext context = JAXBContext.newInstance(Book.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(book, System.out);

You should be expecting something like this in the output:

<?xml version="1.0"?>
<book>
  <isbn>0132350882</isbn>
  <title>Clean Code</title>
</book>

So what’s wrong with it? Pretty much the same thing that’s wrong with object-relational mapping, which is explained in ORM Is an Offensive Anti-Pattern. JAXB is treating an object as a bag of data, extracting the data and converting it into XML the way JAXB wants. The object has no control over this process. Therefore an object is not an object anymore but rather a passive bag of data.

An ideal approach would be to redesign our class Book this way:

public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  public String toXML() {
    // create XML document and return
  }
}

However, there are a few problems with this approach. First of all, there’s massive code duplication. Building an XML document is a rather verbose process in Java. If every class had to re-implement it in its toXML() method, we would have a big problem with duplicate code.

The second problem is that we don’t know exactly what type of wrapping our XML document should be delivered in. It may be a String or an InputStream or maybe an instance of org.w3c.dom.Document. Making many toXML() methods in each object would definitely be a disaster.

Xembly provides a solution. As I’ve mentioned before, it is an imperative language for XML constructions and manipulations. Here is how we can implement our Book object with the help of Xembly:

import org.xembly.Directive;
public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  public Iterable<Directive> toXembly() {
    return new Directives()
      .add("book")
      .add("isbn").set(this.isbn).up()
      .add("title").set(this.title).up()
      .up();
  }
}

Now, in order to build an XML document, we should use this code outside the object:

final Book book = new Book("0132350882", "Clean Code");
final String xml = new Xembler(book.toXembly()).xml();

This Xembler class will convert Xembly directives into an XML document.

The beauty of this solution is that the internals of the object are not exposed via getters and the object is fully in charge of the XML marshalling process. In addition, the compexity of these directives may be very high — much higher than the rather cumbersome annotations of JAXB.

  • Xembly is an open-source project, so feel free to submit your questions or corrections to Github.
Reference: JAXB Is Doing It Wrong; Try Xembly from our JCG partner Yegor Bugayenko at the About Programming blog.

Yegor Bugayenko

Yegor Bugayenko is an Oracle certified Java architect, CEO of Zerocracy, author of Elegant Objects book series about object-oriented programing, lead architect and founder of Cactoos, Takes, Rultor and Jcabi, and a big fan of test automation.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Richard
9 years ago

Actually, I always think the annotations are too invasive. Maybe someone thinks they are metadata, but the class should not necessarily be for one purpose. When I need these class for other things rather than just XML data binding, these annotations make me uncomfortable. I don’t think the import of annotations in Java is wrong, but I think the abuse of this technique is on the wrong road. Like you said, JAXB, JPA, JAX-WS, JAX-RS all emphasis the usage of annotations. But we developers accept all these as see fit, nobody disagree it aloud. I need the child in the… Read more »

Back to top button