Showing posts with label Jetty. Show all posts
Showing posts with label Jetty. Show all posts

Tuesday, 27 November 2012

Comparing Servlet 3.0 Asynchronous Servlets with Jetty Continuations

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:
  • Response from Remote Web Resource
  • A JDBC connection
  • A JMS message
  • An application event
Because, waiting is an inefficient operation which consumes resources such threads, database connections, buffers etc.

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.
Later, Jetty started adopting above features  except "Applying Filters during dispatch mode" since Jetty 7.

Comparing API: Jetty Continuation Vs Servlet 3.0 Async Servlet

FeatureJetty ContinuationServlet 3.0
SuspendContinuation.suspend(HttpServletResponse)HttpServletRequest.startAsync()
ResumeContinuation.resume()AsyncContext.dispatch()
CompleteContinuation.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;
    }
}