JAX-RS 2.0 : Custom Content Handling

I tried to think of a better title, but failed to come up with one ! Please bear with me…….

The JAX-RS 2.0 specification allows us to seamlessly marshal/unmarshal JAXB objects to/from HTTP request/response bodies. Simply put, we can just work with the domain objects without being worried about the low level XML serialization within JAX-RS based solutions.

Before we begin, here is the GitHub link to the source code referenced below – not much, but just in case you need to peek in

Development environment

  • Java EE 7 (of course!)
  • JDK 8- don’t get excited, there are no lambdas in there as yet!
  • Netbeans 8
  • Wildfly 8 and GlassFish 4 (yes, tested on both servers) – it’s just about switching servers in Netbeans and takes anywhere b/w 15-30 seconds. So it’s not really that big a deal 😉

Let us first go through the use cases which demonstrates the out-of-the-box capabilities of JAX-RS implementations in order to deal with JAXB annotated entities/domain objects over the wire.

Here is a simple example where in we try to ‘get‘ a representation of our domain object which happens to be JAXB annotated POJO

2

 

The below JSON response is obtained when we fire a GET HTTP request. The tool being used here is Postman

1

 

Similarly, the XML response can also be observed by simply toggling the Accept HTTP header to application/xml

3

 

 

Let’s see a case where in we try to ‘post‘ a representation of our domain object (XML/JSON) over the wire

4

 

Fire POST request via Postman

6

 

Snippet for the STDOUT in the server logs (as per code above)

 

5

 

So, we just saw, in JAXRS, domain objects decorated with JAXB annotations allows can be exchanged over the wire in both XML and JSON formats without breaking a sweat!

Consider a scenario where we already have rich domain Java objects available to us. But

  • We do not have access to the source code
  • We cannot really annotate them with JAXB annotations
  • The domain entities are legacy POJOs which are not JAXB compatible

Here is where we can leverage customized content handling feature available in JAX-RS 2.0. The MessageBodyWriter and MessageBodyReader interfaces provide us a way to plug in our customized marshalling/unmarshalling mechanism and allow the JAX-RS run time to take care of the rest!

The example which follows primarily deals with XML and JSON formats, but please note that these interfaces can be used for ‘any’ data formats – the internet is teeming with hundreds of these with new ones popping up daily!

Let’s see some code. . . . again…..

To begin with, in order to simulate a get scenario, let’s just return an instance of a Legacy POJO class from our JAXRS resource method. It’s not JAXB compatible/we do not have the source code to decorate it via JAXB annotations

7

 

How do you think this will get serialized to XML over the wire? Our custom implementation of the javax.ws.rs.ext.MessageBodyWriter interface will facilitate this.

This interface has 3 abstract methods which one would need to implement. The snippet showcases the writeTo() method, which contains the bulk of the transformation logic.

You can read about it further in the Java EE 7 javadocs

8

So, as usual, we ask Postman to validate things for us, and this is what he had to say. No hassles! Imagine if the Legacy POJO representation is fetched from the persistent (DB) store directly – all you need to do is return it since the on-the-wire representation has been taken care of

9

 

Now, the reverse scenario – post an XML representation from our client layer and watch it getting serialized into the Legacy POJO instance. Want to persist it ? Sure, go ahead and fire the Entity Manager 😉  (don’t forget @javax.ejb.Stateless !)

10

How do you think the XML payload sent by the client get converted to our Leagcy POJO instance over the wire? Our custom implementation of the javax.ws.rs.ext.MessageBodyReader interface will make this happen.

13

Call upon Postman, post an XML representation over the wire, and see the results

11

 

Just to ensure that our Legacy POJO indeed got serialized – confirmed via the server STDOUT logs

12

So, with the help of a trivial example, we saw how easy it is for us to define custom transformation/wrapper-like logic for handling custom domain objects/entities/POJOs within JAXRS based implementations.

Couple of observations before signing off

  • JAXRS implementation in GlassFish4 does not support seamless JSON serialization/deserialization via a JAXB decorated POJO. Wildfly 8 worked like a charm! Kudos!
  • On delegation of the marshall/unmarshall process to entity interceptors (reader/writer implementations), the seamless JSON support ceased to work (both in GlassFish as well as Wildfly). Not sure why. I am guessing the the JAXRS implementation is directly fetching the payload from/writing payload to the Input/Output streams respectively, and somehow there is no intermediate layer to factor in the content negotiation

I hope I am not missing a trick here! If you think so, please be kind enough to give me a heads up 🙂

Well, that’s it for now! Happy coding…………!

About Abhishek

Loves Go, NoSQL DBs and messaging systems
This entry was posted in Java, Java EE and tagged , , , , , . Bookmark the permalink.

8 Responses to JAX-RS 2.0 : Custom Content Handling

  1. Pingback: Wildfly 8.0 provides seamless JSON support via its JAXRS 2.0 implementation | Object Oriented . .

  2. Pingback: New in JAX-RS 2.0 – @BeanParam annotation | Object Oriented . .

  3. Hugo Tavares says:

    Abhishek: great article, but I still have some doubts…

    1. I don’t understand need of using all the parameters on methods like “writeTo()”, “isWritable”, etc., on the transform/MessageTransformer.java. Are all that parameters needed/used by that methods or is that something going on that I didn’t get?
    2. Let me see if I got it right: our endpoints will be something like ${serverAddress:port}/gateway/rest/x, where x is one of {get, post, fetch, persist}, yes?
      So what’s the direct relation between that REST endpoints and the MessageTransformer methods?

    Meanwhile I have a suggestion: as I’ve downloaded the code from GitHub, I’d suggest you to make a Maven pom available. so the building process would be quick. I believe it’s a “must have” an GitHub project.

    Thank you so much for your support!

    Like

    • Abhishek says:

      Thanks for passing by Hugo. Glad you liked the content.
      To answer your questions

      1. The writeTo() method belongs to an interface of the JAX-RS API – MessageBodyWriter. We implement the interface within our own application and provide concrete business logic for all its methods. What happens at run time is that JAX-RS calls automatically calls the writeTo method of our (custom) class before writing back the response to the client – of course it uses the logic in the writeTo() method to do so. But why do we need this interface? It is because we need to customize the way we want to define client responses.

      The same things is applicable to a MessageBodyReader – if we want to customize the in which we read client input (HTTP request contents) in a specific way. we can implement this interface and JAX-RS will automatically call the logic in the readFrom() method

      1. There is no direct relationship. If you consider the example of a POST request,the correlation happen via a combination of the @Consumes annotation of our JAX-RS Resource class and the MessageBodyReader implementation well as the parameter in JAX-RS method and the parameterized type of the MessageBodyReader implementation.

      As far as the Maven pom goes – I agree. Will try to change the source code to reflect it and apply this suggestion for my future posts

      Like

  4. Scott Van Wart says:

    Nice article! I like that you included a note about the Wildfly/Glassfish duality. I’ve been trying to code as exclusively as I can towards Java EE but there are many things that require you to hook into application server-specific functionality that makes your application less portable.

    Any ideas how to customize the JSON output? I understand Wildfly uses Jackson for its JSON serialization but I have no idea how it exposes configuration so you can add custom types, omit null properties and pretty-print the JSON output.

    Like

    • Abhishek says:

      Thank you for the comments!

      FYI – Jersey implementation in GlassFish requires additional configuration to get the JSON serialization working.

      With regards to JSON output formatting using Wildfly, I guessed that there might be appropriate documentation around this already.
      I looked into RESTEasy documentation (JAX-RS implementation in Wildfly) – http://docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html_single/index.html#json
      Peeked into specific Wildfly dev docs – https://docs.jboss.org/author/display/WFLY8/JAX-RS+Reference+Guide
      Surprisingly – not much information here !

      On the contrary, Jersey has good documentation around this 🙂 – https://jersey.java.net/documentation/latest/media.html#json

      You can probably try the mailing lists (Wildfly or RESTEasy) – I am pretty sure you’ll get your answer! Let me know if I can be of any other help..

      Like

      • Scott Van Wart says:

        I found out a little too late for my sanity that I was coding against a much older version of Jackson that ships with Wildfly but isn’t used with JAX-RS by default. It’s the FasterXML-branded Jackson provider that’s used instead. Once I got that out of the way, my MessageBodyWriter implementation can use my already-customized JSON serializer object by looking it up with CDI.current(). Then writeTo() is basically a one-liner from there.

        Simply having a MessageBodyWriter that @Provides(“application/xml”) overrides the default JSON serialization.

        GSON was quite nice in a lot of areas but I found Jackson much more configurable once you get a hang of the configuration interfaces.

        Like

Leave a comment