Proxy Client on Top of JAX-RS 2.0 Client API

May 4th, 2012 by Martin Leave a reply »

UPDATE (7/3/2012): Proxy-client module is now part of the regular workspace (instead of incubator) and get’s pushed to maven along with other Jersey modules, so no need to build it manually anymore.

Several JAX-RS 1.x implementations are providing proxy client API as one of the ways to access web services. The basic idea is you can attach the standard JAX-RS annotations to an interface, and then implement that interface by a resource class on the server side while reusing the same interface on the client side by dynamically generating an implementation of that using java.lang.reflect.Proxy calling the right low-level client API methods.

Jersey 1.x client API (and now JAX-RS 2.0 client API) leverages the fact REST (and HTTP) defines the standard set of operations, so unlike for JAX-WS type of web services, which are verb-centric, for RESTful web services the interface is uniform and thus there is no need for generating client proxies. The standard client API is static (has fixed set of operations – get, put, post, delete, …). Proxy client API may be seen as evil, as it creates tighter coupling between services and clients. However, some people do find it useful and it provides better opportunities for reusing JAX-RS concepts between services and clients, including name-bound interceptors, for example.

Few weeks back I quickly “hacked” a proxy client factory for Jersey as part of Jersey 2.0 and made some small incremental improvements since then. It is based purely on the current draft of the standard JAX-RS 2.0 client API, so should be usable with any JAX-RS 2.0 implementation, not just Jersey. Currently it lives in the “incubator” subfolder of Jersey 2.0 workspace, so if you want to give it a try, you have to check it out and build it yourself. The project includes a test that illustrates the usage, and also a simple example.

Building the Proxy-Client Project

To build it, first clone the Jersey repository, build Jersey, then switch to the proxy-client folder and build the proxy-client project. The following shell commands do that (assuming you have git and mvn installed):

git clone ssh://[] jersey
cd jersey
mvn install
cd incubator/proxy-client
mvn install

Using/Playing with the Proxy-Client

The project has just one class – WebResourceFactory. Here is how it can be used:

Let’s say you want to access a web resource available at a URI that could be represented by the following URI template:{book-id}

Let’s assume this resource can produce and consume application/json and application/xml and supports GET, PUT and DELETE operations. There is also a parent resource – which accepts GET (returns a list of books) and POST (creates a new book). Here is one example of how you can model it using the interfaces with JAX-RS annotations and then access these resources using those interfaces and WebResourceFactory class:

Interface representing the “books” resource:

public interface BooksResource {
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    List<Book> getBooks();

    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    Response createBook(Book book);

    BookResource getBookResource(@PathParam("bookid") String bookId);

Interface representing “books/{bookid}” subresource:

public interface BookResource {
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    Book get();

    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    Book update(Book book);

    void delete();

Accessing it from your application:

// create a new JAX-RS 2.0 target pointing to the root of the web api
Target t = ClientFactory.newClient().target("");

// create a new client proxy for the BooksResource
BooksResource booksRsc = WebResourceFactory(BooksResource.class, t);

// get list of books
List<Book> books = booksRsc.getBooks();

// get book resource by ID
BookResource bookRsc = booksRsc.getBookResource(bookId);
// get book object
Book myBook = bookRsc.get();
// delete book

I hope you got the idea. As you can see, the proxy factory can handle path parameters and can automatically create proxies for sub-resources. It can also handle other kinds of parameters such as header parameters, query parameters, form parameters and cookie parameters.

Give it a try and let us know what you think.


  1. Cemo Koc says:

    It will be the biggest contribution to Jersey and Webservices land. Looking forward it.

  2. kfis says:

    Great! I just wanted to implement something like this just now, because it seems an obvious extension. I am glad you already did it, that safes me some headache :) Great work!

  3. rfecher says:

    I really love the concept of the proxy client and think its tremendously benificial. However, I initially did not realize certain parameters were not intended to be supported by the proxy client. In particular, it appears multipart/form-data is not supported at all via the proxy client. Is there any intention for the future of supporting this and, in particular, handling FormDataParam annotations? Thanks!

  4. Andy says:

    I see in your example that you create a “Target t”. Do you mean WebTarget? If not, where is that Target class defined?

    • Martin says:

      This blog pre-dates the final JAX-RS 2.0 spec. – at that point of time the class was named Target. Later it got renamed to WebTarget.

  5. Alex says:

    Hi, How do you handle the POST? Especially something like this:
    List saveBooks(List list);


  6. Alex says:

    Ah…meant to say:

    List\ saveBooks (List \ list);

  7. Nelson Christos says:

    Is there any possibililty of handling exceptions. I see that the invoke method throws Throwable, and the class cannot be extended to decorate the invoke method for catching Throwable. This leaves only the option of copy pasted the class and handle exception.

  8. Nelson Christos says:

    let it be..i can handle those in the filter or interceptor

Leave a Reply