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:
- I don’t want to mess around with a crappy API.
- I want to encapsulate the consumption of the service in a plain Java object.
- I just want to consume REST services, so the library should have a small footprint.
- 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.
My 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
@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( "https://server:port/root",
new CustomProvider() );
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 ;).