28 March 2013

JAX-RS 2.0 preview (updated)

Here's an overview of the most important new features in JAX-RS 2.0 (JSR339).
The JSR is currently in public review, so this is subject to change.

  • Asynchronous REST web services
  • REST web services are based on servlets. So the new asynchronous REST support looks a lot like the new asynchronous servlet support.
    The response to an asynchronous web service can be delegated to another thread.
     The webservice needs to pass the asynchronous response, to allow it to send a response.

    @Path ("/rest2/async")
    public class NoWaiter{
      @Asynchronous
      @GET 
      public String delegate(@Suspended AsyncResponse ctx) {
        // put context on a queue
        // for job to be picked up by a thread
        bloq.add(ctx);
        // exit immediatly
      }
    }
    
    class Handler implements Runnable{
      public void run(){
        AsyncResponse ctx bloq.take();
        // return response
        ctx.resume("response");
      }
    } 
  • Client API
  • Similar to Jersey 1 client API 
    Client client = ClientFactory.newClient();
    String result = client.target(“http://reasonsto.be”)
      .request("text/plain")
      .get(String.class); 
    
    Chaining async() in the call, the client becomes asynchronous:
    Future<String> result = client.target(“http://reasonsto.be”)
      .request("text/plain")
      .async()
      .get(String.class);
    You can also pass a listener to the asynchronous client:
    Future<String> result = client.target(“http://reasonsto.be”)
      .request("text/plain")
      .async()
      .get(new Hark()); 
    
    class Hark implements InvocationCallback<String>
    {
    public void completed(String result) {…}
    public void failed(InvocationException err) {…}
    }
  • Filters and Entity Interceptors
    • Similar to Jersey 1 filters (and servlet filters)
    • Entity Interceptors wrap around the HTTP body reading/writing using a service method
    • Filters wrap around an entire HTTP message
      • ContainerResponsFilter 
      • ContainerRequestFilter
        • @PreMatch: run before JAX-RS resource method is selected
        • @PostMatch: run after JAX-RS resource method is selected
    • Binding
      • Global
        •  @Provider
      • Local 
        • Using DynamicFeature
        • Using @NameBinding
          • Indicate that the usage of this resourcemethod is to be logged, using our own annotation:
          • @LogMe
            @GET
            @Produces("text/html")
            public String getXml(){ 
              return "<html>...</html>"
            }
            
          • Define the annotation
          • @NameBinding
            public @interface Logme{}
            
          • Implement the annotation
          • @LogMe
            public class LoggerLoggingFilter 
              implements ContainerRequestFilter, ContainerResponseFilter {
            // your logging code 
            }
            
        • Dynamic
          1. The filter is bound using one of the above methods, but there is an extra check to see if the filter should be applied
          2. The filter must implement the DynamicBinding interface
          3. The filter is applied only if the isBound() method returns true 
      • Client side filters are supported as well
    • JSR303 validation
    • @Produces allows server to specify a mime type preference, using the qs attribute
    • Form class can be used as a resource method argument to capture a map of query parameters (shorthand for UriInfo.getQueryParameters()).