# Asynchronous JAX-RS

This chapter covers asynchronous programming support in JAX-RS and some of its potential gotchas

## Basics of server side async JAX-RS

JAX-RS 2.0 includes a brand new API for asynchronous processing which includes server as well as client side counterparts. Being asynchronous inherently implies request processing on a different thread than that of the thread which initiated the request

* From a client perspective, it prevents blocking the request thread since no time is spent waiting for a response from the server.&#x20;
* Similarly, asynchronous processing on the server side involves suspension of the original request thread and  initiation of request processing on a different thread, thereby freeing up the original server side thread to accept other incoming requests.&#x20;

The end result of asynchronous execution (if leveraged correctly) is scalability, responsiveness and greater throughput.

## Server side async

On the server side, asynchronous behaviour is driven by

* `@Suspended`: annotation which instructs the container to inject an instance of AsyncResponse and invoke the method asynchronously
* `AsyncResponse`: bridge between the application logic and the client request

An instance of `AsyncResponse` can be transparently injected as a method parameter (of a JAX-RS resource class) by annotating it with `@Suspended`. This instance serves as a callback object to interact with the caller/client and perform operations such as response delivery (post request processing completion), request cancellation, error propagation, and so forth

```
//Async JAX-RS in action

@Path("async")
@Stateless
public class AsyncResource {

 @Resource
 ManagedExecutorService mes;

 @GET
  public void async(@Suspended AsyncResponse ar) {

     String initialThread = Thread.currentThread().getName();
     System.out.println("Thread: "+ initialThread + " in action...");

        mes.execute(new Runnable() {
         @Override
         public void run() {
          try {
             String processingThread = Thread.currentThread().getName();
             System.out.println("Processing thread: " + processingThread);

             Thread.sleep(5000);
             String respBody = "Process initated in " 
             + initialThread + " and finished in " + processingThread;

             ar.resume(Response.ok(respBody).build());                                       
              } 
              catch (InterruptedException ex) {
              //ignored. . . don't try this in production!
                  }
                }
            });

        System.out.println(initialThread + " freed ...");
    }
}
```

Since we have clearly expressed our asynchronous requirements, the container will ensure that

* the calling thread is released
* the actual business logic is executed in a different thread (in this case its the thread pool taken care of the by the [Managed Executor Service](https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html) in the Java EE container - thanks to [Concurrency Utilties](https://jcp.org/ja/jsr/detail?id=236) in Java EE 7)

### Things to watch out for

Although the calling (request) thread is released, the underlying I/O thread still blocks until the processing in background thread continues.In the above example, the caller would have to wait 5 seconds since that's the delay we have purposefully introduced within the code. In simple words, the client (e.g. browser executing a HTTP GET) keeps waiting until the business logic execution is finished by calling the `resume` method of the injected `AsyncResponse` object

### Timeouts to the rescue

One can specify a time out period after which the client gets back a HTTP 503 Service Unavailable response (default convention)

```
//Basic async timeout config

@Path("async")
@Stateless
public class AsyncResource {

    @Resource
    ManagedExecutorService mes;

    @GET
    public void async(@Suspended AsyncResponse ar) {
        ar.setTimeout(3, TimeUnit.SECONDS); //setting the time out to 3 seconds
        String initialThread = Thread.currentThread().getName();
        ......
    }
}
```

### Fine grained time outs

The default behaviour (HTTP 503 on time out) might not be suitable for all use cases. For example, you might want to implement a solution where a tracking identifier needs to be sent to the client (for future) if the actual processing does not finish in due time (before timeout triggers). Having the ability to send a custom HTTP response on time out can prove useful. The `AsyncResponse` API makes this possible via the notion of a [time out handler](http://docs.oracle.com/javaee/7/api/javax/ws/rs/container/TimeoutHandler.html). You can do this by

* a direct HTTP response (see below example)
* via an exception (by passing an instance of \`Throwable to [AsyncResponse.resume](http://docs.oracle.com/javaee/7/api/javax/ws/rs/container/AsyncResponse.html#resume-java.lang.Throwable-))

```
//fine grained timeout config

@GET
public void async(@Suspended AsyncResponse ar) {
  ar.setTimeout(3, TimeUnit.SECONDS);
  ar.setTimeoutHandler(new TimeoutHandler() {
    @Override
      public void handleTimeout(AsyncResponse asyncResponse) {
          //sending HTTP 202 (Accepted)
          asyncResponse.resume(Response
          .accepted(UUID.randomUUID().toString())
          .build()); 
      }
});
```

## Client side async using the JAX-RS Client API

Using asynchronous behaviour on the client side is pretty easy. All you need to do is obtain an instance of AsyncInvoker by calling [async](http://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Invocation.Builder.html#async--) on the `Invocation.Builder`

```
//Client side async

Client client = ClientBuilder.newBuilder().build();
WebTarget target = client.target("https://api.github.com/search/users?q=abhirockzz");

Invocation.Builder reqBuilder = target.request();
AsyncInvoker asyncInvoker = reqBuilder.async();
Future<Response> futureResp = asyncInvoker.get();

Response response = futureResp.get(); //blocks until client responds or times out
String responseBody = response.readEntity(String.class);
```

> AsyncInvoker interface supports asynchronous invocation with dedicated methods (get(), post(), put() and so on) for standard HTTP actions: GET, PUT, POST, DELETE, HEAD, TRACE, and OPTIONS.

### Response handling via Callbacks and Futures

Once registered, an implementation of the `InvocationCallback` will automatically be executed once the asynchronous request is processed. It provides the ability to account for both successful and exceptional scenarios. In the event a Future object is obtained and no callback has been registered, manually poll it in order to interact with the response. `isDone`, `get`, `cancel` are some of the methods that can be invoked

```
//Client side async callback

Client client = ClientBuilder.newBuilder().build();
WebTarget target = client.target("https://api.github.com/search/users?q=abhirockzz");

Invocation.Builder reqBuilder = target.request();
Invocation invocation = reqBuilder.buildGet();

Future<Response> future2 = 
  invocation.submit(
    new InvocationCallback<Customer>(){
    public void completed(Customer cust){
        System.out.println(
          "Customer ID:" + cust.getID());
    }
     public void failed(Throwable t){
        System.out.println(
          "Unable to fetch Cust details: " + 
          t.getMessage());
      }
});
```

### Client side gotchas

As you might have already observed, async behaviour in (server side) JAX-RS is not the same as in other typical async APIs i.e. the client is still blocked. One should use the `async` method (as demonstrated above) to call a server side REST API in an async manner even if the server REST API itself is asynchronous in nature (implemented using `@Suspended` AsyncResponse\`) .

> Do not remain under the impression that your client thread will return immediately just because the server API is async

```
//Client side async gotcha!

public Response test() throws Exception{
    Client client = ClientBuilder.newBuilder().build();
    WebTarget target = client.target("http://localhost:8080/jaxrs-async-service/async");

    Invocation.Builder reqBuilder = target.request();
    //this will block until server responds or triggers out (even if its aysnc)
    Response response = reqBuilder.get(); 

    String responseBody = response.readEntity(String.class);
    return Response.status(response.getStatus()).entity(responseBody).build();
}
```

The call to async returns an instance of [Future](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html?is-external=true) object - and you might already know, the \[get]\(<http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get(>)) method (of `Future`) blocks. So use it with care and at the correct point in your application logic
