Why do we need Asynchronous Servlets?
Asynchronous Servlets are useful when a Servlet needs to wait for resources or events. For example, a Servlet may need to wait for:
Containers implementing Asynchronous Servlets:
The Servlet 3.0 asynchronous API introduced some new asynchronous features not supported by jetty 6 continuations:
Asynchronous Servlets are useful when a Servlet needs to wait for resources or events. For example, a Servlet may need to wait for:
- Response from Remote Web Resource
- A JDBC connection
- A JMS message
- An application event
Containers implementing Asynchronous Servlets:
- Jetty 6 supporting Continuations
- Containers implementing Servlet 3.0
- Jetty 7( onwards supports both Jetty Continuations and Servlet 3.0 Asynchronous Servlets
How does Asynchronous Servlets Work:
- Servlet/Filter can begin asynchronous processing
- Thread will return to the container after the asynchronous processing of the request has started. The Servlet response will not be committed like default Servlet Life cycle.
- Another thread may either
- generate the response and call complete
- or dispatch the request to run in container context.
Servlet 3.0 introducing new features compared to Jetty 6
The Servlet 3.0 asynchronous API introduced some new asynchronous features not supported by jetty 6 continuations:
- Ability to complete an asynchronous request without re-dispatching
- Listeners for asynchronous events
- Dispatching asynchronous requests to specific contexts and/or resource
- Support for wrapping requests and responses.
- Applying Filters during dispatch mode.
Comparing API: Jetty Continuation Vs Servlet 3.0 Async Servlet
Feature | Jetty Continuation | Servlet 3.0 |
---|---|---|
Suspend | Continuation.suspend(HttpServletResponse) | HttpServletRequest.startAsync() |
Resume | Continuation.resume() | AsyncContext.dispatch() |
Complete | Continuation.complete() | AsyncContext.complete() |
Understanding Asynchronous Servlets(Code):
Lets take an example where a Servlet blocks while waiting for Remote Web Service call to return and try to understand how the Servlets were written without the invent of Asynchronous Servlets , Jetty 6 Continuations and Servlet 3.0 Asynchronous Servlets.
Synchronous Servlets
public class RemoteWebServiceServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) {
Object result = makeRemoteWebService(...);
writeResponse(result);
}
}
Asynchronous Servlet using Servlet 3.0
@WebServlet(async=“true”)
public class AsyncServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) {
// Check if request it is not async dispatch
if (!req.isAsyncStarted()) {
AsyncContext ctx = req.startAsync(req, res); //Start Async Processing
ctx.start(new RemoteServiceHandler() implements Runnable {
public void run() {
Object result = makeRemoteWebService(...);
request.setAttribute("result", result);
ctx.dispatch(); // Re-dispatch/ resume to generate response
}
});
} else {
Object result = request.getAttribute("result");
writeResponse(result);
}
}
}
Asynchronous Servlet using Jetty Continuations:
public class AsyncServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) {
/ // Check if request it is not async dispatch
Object result = request.getAttribute("result");
if (result == null) {
Continuation continuation = ContinuationSupport.getContinuation(request);
continuation.suspend(response); //Start Async Processing
threadpool.submit(new RemoteServiceHandler() implements Runnable {
public void run() {
Object result = makeRemoteWebService(...);
request.setAttribute("result", result);
continuation.resume(); // Re-dispatch/ resume to generate response
}
});
} else {
Object result = request.getAttribute("result");
writeResponse(result);
}
}
}
Internals of Servlet 3.0 Async and Jetty 6 Continuations:
Now, we will try to understand how Servlet 3.0 Async and Jetty 6 Continuations work internally. Infact, both work in the same way. If you see below, there is a single implementation class for both Servlet 3.0 Async and Jetty 6 Contination:
public class AsyncContinuation implements AsyncContext, Continuation {...........
}And the below code shows that Jetty HttpServletRequest implementation internally uses Continuation API:
public class Request implements HttpServletRequest {
..............
public AsyncContext startAsync() throws IllegalStateException
{
if (!_asyncSupported)
throw new IllegalStateException("!asyncSupported");
_async.suspend();
return _async;
}
}