JAX-RS Providers Part I

Providers

They are nothing but implementations of specific JAX-RS interfaces which provide flexibility and extensibility. They either need to be annotated with the @Provider annotation for automatic detection by the JAX-RS container or need to explicitly configured

In this lesson, we are going to cover two providers

  • Message Body Reader: HTTP payload to Java object transformers

  • Message Body Writer: convert Java object into HTTP payloads before sending them to the caller

  • JAX-RS support for JSON-P

Message Body Reader

A MessageBodyReader is an interface whose implementation supports the conversion of HTTP request content to a Java type which can then be consumed by your JAX-RS application.

Default support

Every JAX-RS implementation provides out-of-the-box support for existing data types (i.e. a default Message Body Reader is provided) such as String, primitives, InputStream, Reader, File, byte array (byte[]), JAXB annotated classes, JSON-P objects. The same is applicable for Message Body Writers as well (see the next topic)

It's best to understand this with the help of an example

//Message Body Reader implmentation

@Provider
@Consumes(MediaType.APPLICATION_XML)
public class CustomerDataToCustomerJPAEntity 
    implements MessageBodyReader<CustomerJPA> {


    //implementation for MessageBodyReader interface

    @Override
    public boolean isReadable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {

        //return true unconditionally - not ideal. one can include checks
        return true;
    }

    @Override
    public LegacyPOJO readFrom(Class<LegacyPOJO> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, String> mm, InputStream in) throws IOException, WebApplicationException {

        JAXBContext context = null;
        Unmarshaller toJava = null;
        CustomerJAXB jaxbCust = null;
        CustomerJPA jpaCust = null;

        try {
            // unmarshall from XML/JSON to Java object

             context = JAXBContext.newInstance(CustomerJAXB);
             toJava = context.createUnmarshaller();
             jaxbCust = (CustomDomainObj) toJavaObj.unmarshal(in);

             //build JPA entity
                jpaCust = new CustomerJPA(jaxbCust.getUniqueID(), jaxbCust.getName());
        } catch (JAXBException ex) {
            Logger.getLogger(MessageTransformer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return jpaCust;
    }
}

What's going on here ?

  • client sends XML payload (in HTTP message body representation)

  • JAX-RS scans the available Message Body Readers and finds our implementation - CustomerDataToCustomerJPAEntity

  • As per our requirement, we first transform the raw payload into an instance of our JAXB annotated model class (CustomerJAXB) and then build an instance of our custom JPA entity (CustomerJPA)

Benefits

  • Separates the business logic from data transformation code - the conversion is transparent to the application

  • One can have different implementations for conversion of different on-wire representations to their Java types and qualify them at runtime by specifying the media type in the @Produces annotation e.g. you can have separate reader implementations for a GZIP and a serialised (binary) representation to convert them to the same Java type

Message Body Writer

Now that we have seen Readers, Message Body Writers are easy to understand - they are the exact opposite i.e. an implementation of a Message Body Writer transforms a Java type to an on-wire format to be returned to the client.

The below example, is the exact opposite (mirror image) of what was demonstrated earlier. This time, we are returning an instance of our custom class without including any transformation logic in our JAX-RS resource classes - it's encapsulated within our MessageBodyWriter implementation

JAX-RS and JSON-P integration

This section talks about support for JSON-P in JAX-RS 2.0

JSON-P

The JSON Processing API (JSON-P) was introduced in Java EE 7. It provides a standard API to work with JSON data and is quite similar to its XML counterpart - JAXP. JSON-B (JSON Binding) API is in the works for Java EE 8.

Support for JSON-P in JAX-RS 2.0

JAX-RS 2.0 (also a part of Java EE 7) has out-of-the-box support for JSON-P artifacts like JsonObject, JsonArray and JsonStructure i.e. every JAX-RS 2.0 compliant implementation will provide built in Entity Providers for these objects, making it seamless and easy to exchange JSON data in JAX-RS applications

Let's look at a few code samples

These are pretty simple examples, but I hope you get the idea....

Few things to be noted

  • No need to write custom MessageBodyReader or MessageBodyWriter implementations. As mentioned previously, the JAX-RS implementation does it for you for free

  • This feature is not the same as being able to use JAXB annotations on POJOs and exchange JSON versions of the payload (by specifying the application/xml media type) - this is also known as JSON binding and it is one of the potential candidates for Java EE 8. I have experimented with this and observed that GlassFish 4.1 (Jersey) and Wildfly 8.x (RESTEasy) support this by default

Last updated

Was this helpful?