Using JAX-RS With JAXB

Java Architecture for XML Binding (JAXB) is an XML-to-Java binding technology that simplifies the development of web services by enabling transformations between schema and Java objects and between XML instance documents and Java object instances. An XML schema defines the data elements and structure of an XML document. You can use JAXB APIs and tools to establish mappings between Java classes and XML schema. JAXB technology provides the tools that enable you to convert your XML documents to and from Java objects.

There are many tutorials and examples of using JAX-RS to create RESTful web services, but most fall short of explaining how to produce and consume complex object graphs using XML and JAXB. This article will show how easy it can be, several approaches to where you place the annotations, and how you can configure them.

Lets start with the root XML element. I chose to call mine GetBooksResponse, and use it as a container for a collection of Book objects and a Student object. You don’t need to follow this convention.GetBooksResponse.java

JAXB’s default naming convention is to use your class or bean getter name as-is, but starting with a lower case letter. In this example, once marshaled to XML the element names will be getBooksResponse, student, and books. I will show an example of how to override the default naming later in this article.

Also notice that I placed the @XmlElement annotations on the getter methods instead of on the private fields. When placed on the private fields, JAXB will give you an error unless you add @XmlAccessorType(XmlAccessType.FIELD) at the class level.

Finally, notice the @XmlElementWrapper annotation on the List collection. This makes JAXB wrap all of the order XML elements inside of an orders XML element. This annotation can be used with an array instead of a List too.Student.java

In the example above, we use @XmlType at the class level instead of @XmlRootElement because it is not the root element. Also notice the name parameter in each of the annotations. This is how you override JAXB’s default element naming.

In the example above I used the @XmlAccessorType(XmlAccessType.FIELD) to allow me to place the @XmlElement annotations on the private fields instead of on the getter methods.

Also notice the propOrder parameter of the @XmlType annotation. By default JAXB will book the elements alphabetically. Use the propOrder parameter to specify the order when marshaling to XML. The values are the bean names, not the overridden names in the @XmlElement(name = “overridenName”) annotation.

Finally, notice the @XmlElementWrapper used on a PublishedBooks[] array. It works with arrays and Lists.

In the example above there are no setter methods that correspond to getSubTotal, getTax and getTotal. Now lets create a JAX-RS RESTful web service that can return this object graph in the response.BookResource.java

Notice the @Produces(“text/xml”) annotation, and that the method returns a GetBooksResponse object. Since the GetBooksResponse is annotated with JAXB annotations, JAX-RS will automatically marshal the response to XML.

Next lets add a method that takes part of the object graph as a request parameter. We’ll start by creating an object to represent the XML root element:UpdateBookRequest.java

Since the UpdateBookRequest is annotated with JAXB annotations, JAX-RS will automatically unmarshal it from XML.

This example returns a javax.ws.rs.core.Response built using javax.ws.rs.core.ResponseBuilder. You can use ResponseBuilder to set response headers, the status code, and many other things. The response body is called the entity, and you can place anything in it. For example, a String, or a JAXB annotated object graph.

This example also throws an BookNotFoundException:BookNotFoundException.java

The custom exception extends the WebApplicationException in JAX-RS. There are many constructors in WebApplicationException. I chose to use the one that lets me provide the complete response data.web.xml