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.
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.
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 asynchronouslyAsyncResponse
: 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
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 in the Java EE container - thanks to Concurrency Utilties 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)
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. You can do this by
a direct HTTP response (see below example)
via an exception (by passing an instance of `Throwable to AsyncResponse.resume)
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 on the Invocation.Builder
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 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
The call to async returns an instance of Future 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
Last updated