Consuming REST services in Java the cool way

When creating a REST API with Java you probably go with JAX-RS . It’s a nice and well thought-out standard. Having the services encapsulated as plain Java objects with some annotations feels good to me. But this is all different when it comes to consuming REST services. During the last month I have searched for libraries that meet the following expectations:

  1. I don’t want to mess around with a crappy API.
  2. I want to encapsulate the consumption of the service in a plain Java object.
  3. I just want to consume REST services, so the library should have a small footprint.
  4. I would love to reuse the specification of REST service which I have already used for the server side.

I will skip expectation number 1 because I don’t want to point fingers ;). Coming to the second point, my thoughts are that encapsulating a service is not the problem. I have also decided to encapsulate it by myself, if there is no other way. My research has led me to only one library that does this job for me. This is CRest, an annotation based API that is pretty similar to the one from JAX-RS and partly compatible with JAX-RS 1.0. But “pretty similar”and “partly compatible” isn’t enough from my point of view because this leads to duplicated interface definitions and version conflicts when using a newer JAX-RS version. I have also looked at libraries like the well-known Apache HTTP Client, an URLConnection abstraction from Kevin Sawicki or the JAX-RS 2.0 Client API and so on. Every library I looked at didn’t meet my expectations on one or two points.

overall 300x184 Consuming REST services in Java the cool wayMy optimal vision of consuming REST services with Java would be to reuse the interface I have defined for the server-side (the @Path resource) and to create a consumer out of it automatically. Having such a solution would also guarantee compile time safety when building the server and the client because you need to define your interface just once and reuse it on both sides. Last week I found almost exactly what I was looking for. Apache CXF provides a proxy based API that takes a @Path resource and creates a consumer out of it. But as it is with most libraries, this cool functionality is part of a monolith. I don’t want 200 lines of dependency definitions, I don’t want dependencies to JAX-WS when doing JAX-RS and I don’t want to use a communication framework when I just want to consume some REST services  ;).

In the end I found myself implementing the library I needed on my own. The result is a very small library that consists of only about 500 lines of code and has the very fancy name JAX-RS Consumer. It gives you the opportunity to transform your @Path interface into a consumer object. Under the hood the Jersey client is used which is taking over tasks like the wiring between @Path and @Providers, sending the actual request, and so on. The single plain Java API it provides is best explained with an example:

MyResource resource = ConsumerFactory.createConsumer( "http://server:port/root", 
                                                    MyResource.class, 
                                                    new CustomProvider() );
resource.doSomething();

As you can see there is a ConsumerFactory which takes several arguments.  The first one is the base url of the service provider. The second is the class object of your @Path interface. The third is an optional varargs array of @Providers. It returns an instance of your service interface which sends the defined requests when accessing the object’s methods. If you want to try this out I have written a simple example that consumes a little GitHub API.

There is one more thing. The JAX-RS Consumer also has an OSGi integration, but this is a topic for another post. If you want to get familiar with the consumer here are the resources you will probably be looking for . Don’t be shy to open issues for it, it’s in an early state ;).

 

3 Responses to “Consuming REST services in Java the cool way”

  1. iskorn says:

    I’ve did something similar recently. However I used a more complicated (but possibly more flexible) approach. First of all it was based on the assumption that server-side is written in Java using standard JAX-RS annotations and we have an access to the server bytecode. Having a list of server-side resources (class names) one can analize them via Reflection API and generate client-side interfaces (I used Velocity for the code generation). After that at the client-side one can easily implement dynamic proxies for all the resources. It is possible to have a synchronous or asynchronous client – all you need is to change the Velocity template and implement a corresponding logic in your client-side proxy. I’ve used this approach to implement 3 different flavours of the client-side API for my RESTful service. Actually this approach was inspired by RestyGWT. In fact it can be extended to non-Java client (all you need is to choose HTTP client API and (de)serialization framework for the content marchalling). The huge advantage is that your clinet-side API will be always in sync with the server.

  2. Christian Baranowski says:

    What are the points which you are missing in the resteasy Client Framework?(http://docs.jboss.org/resteasy/docs/2.3.5.Final/userguide/html_single/index.html#RESTEasy_Client_Framework)

    I really like it…

3 responses so far

Written by . Published in Categories: Planet Eclipse

Published:
Nov 27th, 2012
Follow:

Twitter Google+ GitHub Facebook