Asynchronous processing

Traditionally, servlets have created a single thread per request in Java web applications. After a request is processed, the thread is made available for other requests to use. This model works fairly well for traditional web applications, for which HTTP requests are relatively few and far between. However, most modern web applications take advantage of Ajax (Asynchronous JavaScript and XML), a technique that makes web applications behave much more responsively than traditional web applications. Ajax has the side effect of generating a lot more HTTP requests than traditional web applications, if some of these threads block for a long time waiting for a resource to be ready, or do anything that takes a long time to process, it is possible our application may suffer from thread starvation.

To alleviate the situation described in the previous paragraph, the Servlet 3.0 specification introduced asynchronous processing. Using this new capability, we are no longer limited to a single thread per request. We can now spawn a separate thread and return the original thread back to the pool, to be reused by other clients.

The following example illustrates how to implement asynchronous processing using the new capabilities introduced in Servlet 3.0:

package net.ensode.javaee8book.asynchronousservlet; 
 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.servlet.AsyncContext; 
import javax.servlet.ServletException; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
@WebServlet(name = "AsynchronousServlet", urlPatterns = {
"/AsynchronousServlet"},
asyncSupported = true) public class AsynchronousServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final Logger logger = Logger.getLogger(AsynchronousServlet.class.getName()); logger.log(Level.INFO, "--- Entering doGet()"); final AsyncContext ac = request.startAsync(); logger.log(Level.INFO, "---- invoking ac.start()"); ac.start(new Runnable() { @Override public void run() { logger.log(Level.INFO, "inside thread"); try { //simulate a long running process. Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(AsynchronousServlet.class.getName()). log(Level.SEVERE, null, ex); } try { ac.getResponse().getWriter().
println("You should see this after a brief wait");

ac.complete();
} catch (IOException ex) { Logger.getLogger(AsynchronousServlet.class.getName()). log(Level.SEVERE, null, ex); } } }); logger.log(Level.INFO, "Leaving doGet()"); } }

The first thing we need to do to make sure our asynchronous processing code works as expected is to set the asyncSupported attribute of the @WebServlet annotation to true.

To actually spawn an asynchronous process, we need to invoke the startAsync() method on the instance of HttpServletRequest that we receive as a parameter in the doGet() or doPost() method in our servlet. This method returns an instance of javax.servlet.AsyncContext. This class has a start() method that takes an instance of a class implementing java.lang.Runnable as its sole parameter. In our example, we used an anonymous inner class to implement Runnable in line; of course a standard Java class implementing Runnable can be used as well.

When we invoke the start() method of AsyncContext, a new thread is spawned and the run() method of the Runnable instance is executed. This thread runs in the background, the doGet() method returns immediately, and the request thread is immediately available to service other clients. It is important to notice that, even though the doGet() method returns immediately, the response is not committed until after the spawned thread finishes. It can signal it is done processing by invoking the complete() method on AsyncContext.

In the previous example, we sent some entries to the application server log file to better illustrate what is going on. By observing the application server log right after our servlet executes, we should notice that all log entries are written to the log within a fraction of a second of each other; the message You should see this after a brief wait doesn't show in the browser until after the log entry indicating that we are leaving the doGet() method gets written to the log.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.188.121