Category

JAXB parent-child cycle problem

I wrote a RESTful web service that was the backend for an iOS app. Since I wrote the the web administration app using Spring @MVC 3, I used that for the web service also instead of Jersey. One cool thing is how transparent the marshaling of your objects is. Here is a simple example.

Notice what you don’t see. (How’s that for a sentence? :)) The web service simply returns a Composer object (obtained from the composerService) – you don’t see any gyrations for returning XML or JSON! If the client requests XML, then Spring will automatically use JAXB to convert your Java object into XML. If Jackson is on your classpath and the client requests JSON then Spring will automatically marshal your object into JSON. Neat. (You can use other marshaling technologies. See the Resources below.)

Unless you’re returning an object graph that includes a bidirectional parent/child relationship.

Here is an example parent which is also a JPA entity. One composer has many works, and a work belongs to one composer. It is not necessary that it be an Entity for the marshaling to work; it’s just that JPA bidirectional associations are commonly used along with the topic at hand.

And here is an example child. Since the relationship is bidirectional, there is a reference to the composer.

Let’s set up a simple object graph with a Composer who has one Work. Then marshal the composer to
stdout with a small helper class.

Oops. It looks like JAXB doesn’t like this. This what the program barfs:

The XML solution

To fix the XML the solution is fairly simple. Just mark the parent as @XmlTransient.

You now get this output.

The Java solution

What about your Java object graph when this XML is deserialized? There is no attribute in the work element for the composer. But, you see that the work is a child element of composer so that information is not lost. Let’s check what happens with a few more utility methods.

Now in the main method let’s test the marshal/unmarshal process. We save the composer to a file and then read it back. Then we look at each work and print out the composer info.

Here is the output.

Since the composer field in Work has been annotated as being XmlTransient, it is not restored on unmarshal. We have to do that ourselves. Luckily it is simple. Just implement this method in the child class (Work) to restore the reference to the parent.

Eye candy

You can specify the ordering of the elements output by JAXB with the XmlType annotation.

Resources

JAXB home page

Spring MVC RequestBody annotation and converters

Download a Maven project for the code contained in this (and other) articles. Run the web service first via jetty:run, and then run the unit tests. For the simple raw test, simply right JAXBHelper as a Java application.

You probably might also know that if you have curl installed you can do this:

4 thoughts on “JAXB parent-child cycle problem”

  1. Thank you !!
    I have been trying to solve this for 2 days.
    the key really was the ->
    @XmlAccessorType(value = XmlAccessType.FIELD)
    on the class.

    1. “On the class” You mean on the class has relationship many (example, Blog –> Comments, Should I put @XmlAccessorType(value = XmlAccessType.FIELD) on the comments? I try two classes but nothing happened… so sad…

Leave a Reply

Your email address will not be published. Required fields are marked *

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