Skip to main content
Blog

Resteasy with JAXB

By 12 december 2013januari 30th, 2017No Comments

Resteasy is the implemenation used in jboss to support the JAX-RS support. It is based on simple servlets mainly configured using annotations (even web.xml can be ommitted when using JEE). Resteasy comes with some nice simple features to create rest web services. Also support for JAXB and JSON is available. By adding some simple tweaks in your objects you want to serialize to xml or json, you can very quickly create some rest services.

 

Rest service endpoint

A resteasy end point can be created in an interface or in a class. I prefer to define the endpoint in an interface. The following example illustrates a simple endpoint called bookEndpoint that should return a list of books in xml format.

interface BookEndpoint {
    @Get
    @Path("/books/author/{author}")
    Response getBooks(@PathParam("author") String author);
}

The endpoint returns a standard resteasy response object. In this response object you should contain the resulting media type and the content.
The @Get annotation represents one of the HTTP methods. For each of the HTTP method an annotation is available.
The @Path annotation represents the relative URL. Possible parameters are notated between curly braces in the URL. All parameters should be represented in the method arguments with an annotation like @Pathparam.

Alternatively you can make the media type and content available directly in the endpoint. This makes the interface with this endpoint more explicit.
You can do this by using the @Produces annotation and giving and returning another object. The following example (BookEndpoint2) illustrates this for the book endpoint.

interface BookEndpoint2 {
    @Produces("text/*+xml")
    @Get
    @Path("/books/author/{author}")
    Bookstore getBooks(@PathParam("author") String author);
}

Resteasy now has to connect the dots. By combining the media type and the content, it will choose a Provider depending on your endpoint definition. A provider is defined by an implementation of the MessageBodyWriter (serializer) and/or MessageBodyReader (deserializer) interfaces.
Resteasy comes out of the box with some providers, like Multipart, JSON and JAXB, but you can also easily define your own implementations of MessageBodyReader and/or MessageBodyWrite.
I will focus on the JAXB implementation.

 

Dependencies

 

I am using Maven. To get all resteasy related artifacts use the following in your dependency management section

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-bom</artifactId>
            <version>3.0.4.Final</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

To be able to use Resteasy you should at least include the jaxrs-api and the resteasy implementation of jaxrs. You can do this by using the following dependencies:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>jaxrs-api</artifactId>
</dependency>

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
</dependency>

This contains the core of resteasy, but does not contain any provider. The JAXB provider can be included by adding the following dependency.

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxb-provider</artifactId>
</dependency>

 

Configuration

 

RestEasy should come out of the box when using JEE. The only thing you have to specify is a class annotated with the @ApplicationPath annotation.
When using RestEasy in J2SE you have to specify the following in your web.xml file.

<context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
</context-param>

<listener>
    <listener-class>
        org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
</listener>

<servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

 

JAXB configuration

When using JAXB Marshallers and UnMarshallers you can set some configuration settings. With RestEasy you can adjust that same configuration using a decorator.
A decorator consists of two parts:

  • Annotation used in your endpoint
  • Decorator class implementing the decorator

For example, you want to set a simple configuration that pretty prints the JAXB output. You create an annotation like this.

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Decorator(
    processor = JaxbMarshallerDecorator.class, 
    target = Marshaller.class)
public @interface JaxbMarshallerConfigurator {

}

and you create the Decorator implementation like this.

@DecorateTypes({ "text/*+xml", "application/*+xml" })
public class JaxbMarshallerDecorator 
    implements DecoratorProcessor<Marshaller, JaxbMarshallerConfigurator> {
    @Override
    public Marshaller decorate(
           Marshaller target, JaxbMarshallerConfigurator annotation, 
           Class type, Annotation[] annotations, MediaType mediaType) {
        try {
            target.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        } catch (PropertyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

By using the @JaxbMarshallerConfigurator in your endpoint the xml will be formatted.

 

JSON using JAXB

 

There is also the possibility (read: cool feature) to output JSON from your JAXB annotated classes. You need an extra provider called the jettison. Add the following dependency to include the jettison provider.

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jettison-provider</artifactId>
</dependency>

You also have to change your enpoint slightly. Of coarse the Media type has to be changed and the @Mapped annotation needs to be specified. The following code is the book endpoint needed to output JSON.

interface BookEndpoint2 {
    @Produces("application/json"")
    @Get
    @Path("/books/author/{author}")
    @Mapped
    Bookstore getBooksJSON(@PathParam("author") String author);
}

However, Jettison is limited to two mapping formats:

  1. Jettison Mapped Convention format
  2. BadgerFish

The first mapping format is the default. By using the @BadgerFish annotation in your endpoint you will get JSON according BadgerFish convention.