Client API - 6.3

Talend ESB Service Developer Guide

EnrichVersion
6.3
EnrichProdName
Talend Data Fabric
Talend Data Services Platform
Talend ESB
Talend MDM Platform
Talend Open Studio for ESB
Talend Real-Time Big Data Platform
task
Design and Development
Installation and Upgrade
EnrichPlatform
Talend ESB

JAX-RS 1.1 does not have a standard Client API. JAX-RS 2.0 will introduce a standard API. CXF JAX-RS offers an HTTP-centric and Proxy-based API.CXF will continue supporting and enhancing its private API for those developers who may want to continue using it even after CXF JAX-RS implements JAX-RS 2.0.

HTTP Centric API

This API lets developers write the HTTP centric code. This fluent API makes it easy to modify the request URI, check the response status and headers. For example:

public class RESTClient {

   public void consumeRESTfulService(String baseAddress) {
      WebClient client = WebClient.create(baseAddress);
      client.type("application/xml").accept("application/xml");
      client.path("/book1");
      // get javax.ws.rs.core.Response directly and check the status, 
      // headers and read the Response.getEntity() input stream
      Response response = client.get();
      // back to the base address
      client.back(true);
      client.path("/book2");
        
      // get a typed response
      Book response = client.get(Book.class); 
   }

}

Proxy API

Proxy based API lets reuse the existing JAX-RS annotated interfaces or implementation classes as proxies. The proxy call will lead to a proper URI and HTTP headers passed to the server, exactly the way the JAX-RS annotated service expects. Proxies can also check the actual HTTP Response, modify request URI and headers, as well as be converted to WebClients. For example, given the following sample interface and the client code:

@Path("books")
public interface BookStore {

   @GET
   @Path("{id}")
   @Produces("application/xml")
   Book getBook(@PathParam("id") long id);

   @POST
   @Consumes("application/xml")
   Response addBook(Book newBook);

   @Path("all")
   BookStore getStore();

   @GET
   Books getAll();

   public class RESTClient {

      public void consumeRESTfulService(String baseAddress) {
         BookStore proxy = 
            JAXRSClientFactory.create(baseAddress, BookStore.class);
        
         // get a single book
         Book book = proxy.getBook(1);
        
         // further introspect the response headers
         Client theClient = WebClient.getClient(proxy); 
         javax.ws.rs.core.Response response = theClient.getResponse();
         checkResponseHeaders(response.getMetadata()); 
        
         // add new book
         Response addNewBookResponse = proxy.addBook(new Book(
            "User Guide")); 
         if (201 == addNewBookResponse.getStatus()) {
            URI bookResourceLocation = 
               URI.create(addNewBookResponse.getMetadata().getFirst(
               "Location"));
            Book theBookProxy = JAXRSClientFactory.create(
               bookResourceLocation, Book.class);
            theBookProxy.getName();  
         } else {
            reportUnexpectedStatus(addNewBookResponse);
         }           

         // get all books
         BookStore proxy2 = proxy.getStore();
         Books books = proxy2.getAll();
      }

}

the proxy.getBook(1) call will lead to a 'GET http://localhost:8080/store/books/1' HTTP request being sent to the server, with Accept header set to application/xml.

Note the proxy.getStore() and proxy2.getAll() calls. The BookStore.getStore() resource method is a subresource locator as it has only a @Path annotation. This locator returns the BookStore root instance itself. Thus proxy.getStore() only returns a proxy and the subsequent proxy2.getAll() call will lead to the 'GET http://localhost:8080/store/books/all' HTTP request being sent.

Reading and Writing HTTP Messages

JAX-RS MessageBodyReader and MessageBodyWriter providers are used to deal with output and input parameters representing HTTP request and response messages, the same way it is done on the server side. Both WebClient and proxy clients can register custom readers and writers if needed, when dealing with custom formats or when the default providers shipped with CXF JAX-RS need to be configured.

For example, a WebClient or proxy call may return a javax.ws.rs.Response instance which usually implies that the client wishes to deal with the HTTP response directly: the status and headers are checked and then the response InputStream returned by default from Response.getEntity() is manually read; in fact, in case of proxies, Response is something a proxy needs to deal with whenever a current proxy method is typed to return Response. Often the Response.getEntity() InputStream can be read by the registered JAX-RS MessageBodyReader providers. This example shows how registering a custom CXF JAX-RS ResponseReader can help:

@Path("books")
public interface BookStore {
   @GET
   @Path("{id}")
   @Produces("application/xml")
   Response getBook(@PathParam("id") long id);
}

public class RESTClient {

   public void consumeRESTfulService(String baseAddress) {
      org.apache.cxf.jaxrs.client.ResponseReader responseReader =
         new org.apache.cxf.jaxrs.client.ResponseReader(Book.class);

      BookStore client = JAXRSClientFactory.create(
         baseAddress, BookStore.class);

      // get a single book
      Response response = client.getBook(1);
      Book book = response.readEntity(Book.class);
   }

}

Exception Handling

WebClient or proxy based code dealing with explicit javax.ws.rs.core.Response responses is expected to handle the error HTTP responses itself. Usually, the code will check the response status and if the status indicates the error then some action is taken, for example, an exception can be thrown.

If the custom class such as Book is expected to be returned then org.apache.cxf.jaxrs.client.ServerWebApplicationException will be thrown in case of the HTTP response status being equal or greater than 400.

When working with proxies and in particular with methods which may throw custom checked exceptions, one or more org.apache.cxf.jaxrs.client.ResponseExceptionMapper providers can be registered during the proxy creation. These mappers can convert javax.ws.rs.core.Responses into custom exceptions as required by a given method signature.

Irrespectively of whether the Response or concrete custom class is expected in response to a given call, org.apache.cxf.jaxrs.client.ClientWebApplicationException will be thrown if the invocation has failed on the client side, for example, no connection has been established, no MessageBodyWriter has been found to write the request message or no MessageBodyReader has been found to read the response message, all on the client side.