Async servlet was introduced in Servlet 3. It’s a great way to deal with thread starvation problem with long running threads.

Async Servlet

Before we jump into understanding what Async Servlet is, let’s try to understand why do we need it.

Let’s say we have a Servlet that takes a lot of time to process, something like below.

If we hit above servlet through browser with URL as https://localhost:8080/AsyncServletExample/LongRunningServlet?time=8000, we get response as “Processing done for 8000 milliseconds!!” after 8 seconds. Now if you will look into server logs, you will get following log:

So our Servlet Thread was running for ~8+ seconds, although most of the processing has nothing to do with the servlet request or response.

This can lead to Thread Starvation – since our servlet thread is blocked until all the processing is done. If server gets a lot of requests to process, it will hit the maximum servlet thread limit and further requests will get Connection Refused errors.

Prior to Servlet 3.0, there were container specific solution for these long running threads where we can spawn a separate worker thread to do the heavy task and then return the response to client. The servlet thread returns to the servlet pool after starting the worker thread. Tomcat’s Comet, WebLogic’s FutureResponseServlet and WebSphere’s Asynchronous Request Dispatcher are some of the example of implementation of asynchronous processing.

The problem with container specific solution is that we can’t move to other servlet container without changing our application code, that’s why Async Servlet support was added in Servlet 3.0 to provide standard way for asynchronous processing in servlets.

Asynchronous Servlet Implementation

Let’s see steps to implement async servlet and then we will provide async supported servlet for above example.

  1. First of all the servlet where we want to provide async support should have @WebServlet annotation with asyncSupported value as true.
  2. Since the actual work is to be delegated to another thread, we should have a thread pool implementation. We can create thread pool using Executors framework and use servlet context listener to initiate the thread pool.
  3. We need to get instance of AsyncContext through ServletRequest.startAsync() method. AsyncContext provides methods to get the ServletRequest and ServletResponse object references. It also provides method to forward the request to another resource using dispatch() method.
  4. We should have a Runnable implementation where we will do the heavy processing and then use AsyncContext object to either dispatch the request to another resource or write response using ServletResponse object. Once the processing is finished, we should call AsyncContext.complete() method to let container know that async processing is finished.
  5. We can add AsyncListener implementation to the AsyncContext object to implement callback methods – we can use this to provide error response to client incase of error or timeout while async thread processing. We can also do some cleanup activity here.

Once we will complete our project for Async servlet Example, it will look like below image.

Async-Servlet-Example

Initializing Worker Thread Pool in Servlet Context Listener

The implementation is pretty straight forward, if you are not familiar with Executors framework, please read Thread Pool Executor.

For more details about listeners, please go through Servlet Listener Example.

Worker Thread Implementation

Notice the use of AsyncContext and it’s usage in getting request and response objects and then completing the async processing with complete() method call.

AsyncListener Implementation

Notice the implementation of onTimeout() method where we are sending timeout response to client.

Async Servlet Example implementation

Here is the implementation of our async servlet, notice the use of AsyncContext and ThreadPoolExecutor for processing.

Run Async Servlet web application

Now when we will run above servlet with URL as https://localhost:8080/AsyncServletExample/AsyncLongRunningServlet?time=8000 we get the same response and logs as:

If we run with time as 9999, timeout occurs and we get response at client side as “TimeOut Error in Processing” and in logs:

Notice that servlet thread finished execution quickly and all the major processing work is happening in other thread.

Thats all for Async Servlet, I hope you liked it.

By admin

Leave a Reply

%d bloggers like this: