The JAX-RS library is used for implementing REST web services in Java. They are designed for quick request-response processing to ensure speed and optimal use of the underlying container thread pool. But there can be scenarios where certain resources need to run for a longer time to process and provide a response. To address these scenarios, JAX-RS has implemented an asynchronous processing mechanism. This feature was introduced in JAX-RS version 2.0. Let us have a look into the JAX-RS Asynchronous processing mechanism.
This means the thread that responds to a request will be a different one than that of the thread that handled the request. In short, the request and response won’t happen in one stretch. There can be a considerable time gap between the two.
Why is it required?
If you are wondering what is the need for such an implementation, there mainly two benefits:
- Consider a synchronous request-response scenario. If a JAX-RS client sends a request that requires long waiting for a response from the server, it is blocking the request thread. The same thread, if released faster, could have been used by some other requests. This is avoided by implementing the asynchronous method.
- Similarly on the server side also, it allows the server to suspend the original request thread and create a new thread for responding to an asynchronous request.
Due to the above-said reasons, the implementation will ensure high throughput, responsiveness, and scalability.
The below given process diagram will give you a clear picture of this concept.
JAX-RS Asynchronous Implementation
There are separate implementations available on the server-side and client-side for asynchronous APIs.
Server-side implementation of Asynchronous processing
On the server-side, the asynchronous behavior is ensured by using:
- AsyncResponse: This class is responsible for bridging the client-side request with the server-side methods. Using this class the server methods update the status of asynchronous processes. Based on this status the underlying logic will take appropriate action. The resource method that is running a long process should call AsyncResponse.resume() so that a response can be sent back to the client.
- @Suspend: This annotation is used to instruct the container to inject the AsyncResponse method and invoke it asynchronously. The resource methods called with AsyncResponse instance will be in the suspended state. One important thing to remember here is that the resource method that is annotated with @Suspend will not be called using a separate thread. It is the responsibility of the programmer to create a new thread for the long-running process and return the caller thread.
One more thing to remember here is to specify a time-out period using AsyncResponse.setTimout(). This will ensure that the client will get back an HTTP 503 (Service Unavailable ) response, in case there are some issues on the server and the resource method could not respond. If this timeout is not specified, the client-side request will end up in a long wait.
Client side implementation of Asynchronous processing
The client side implementation of asynchronous call is pretty easy. The only thing you need to do is get an instance of the AsyncInvoker. This can be done by executing async() function on an instance of Invocation.Builder class. Let us see an example here:
Client restClient = ClientBuilder.newBuilder().build();
WebTarget URL = restClient.target(“https://api.example.com/search/menu?query=pasta”);
Invocation.Builder requestBuilder = URL.request();
AsyncInvoker asyncInvoker = requestBuilder.async();
Future futureResponse = asyncInvoker.get();
Response apiResponse = futureResponse.get();
String responseBody = apiResponse.readEntity(String.class);
In the above example, the highlighted portion explains how to use the asynchronous call on the client-side.
There are lots of features in JAX-RS that help for rapid request-response processing. But the asynchronous feature implementation in JAX-RS helps a developer to give a time lag between request and response processing. This is very useful especially when there is heavy server-side processing required on certain client requests.