Jetty Continuations Example
In this example, we will show how to use Jetty Continuations. Continuations are a way to implement asynchronous servlets. Added advantage of this feature compared to asynchronous feature of Servlet 3.0
api, is that it provides simple and portable interface.
Jetty continuations suspend an HTTP request and releases the thread to the thread pool. It restarts suspended request on an event or occurrence of timeout. This feature allows webservers to scale for heavy loads.
1. Environment
- Windows 7 SP 1
- Eclipse Kepler 4.3
- Java version 7
- Maven 3.0.4
- Jetty version 9.2.15 v20160210
- Servlet-api-3.1
2. Example Outline
In this example, we will first explain what jetty continuations is. We will create an eclipse project for a sample servlet. We will use Jetty Continuations API to suspend/complete with a timeout feature.
3. What is Jetty Continuations?
Jetty Continuations provide a way to use asynchronous servlets. Many web applications have to wait at some stage during processing of HTTP requests. Example
- Chatting application where it waits for an application event
- Waiting for a resource to be available before processing the request (thread, JDBC connection)
- Waiting for a response from a remote service (RESTful or SOAP call to a web service)
Old servlet API used to provide only synchronous servlets, but API 2.5 and later added support for asynchronous servlets. Jetty Continuations API added a change in the servlet API that allows a request to be dispatched multiple times to a servlet. If the servlet doesn’t have all the resources to fulfill the request, then the request is suspended, so that servlet may return from the dispatch without a response being sent. When the waited for resources become available, the request is re-dispatched to servlet, with a new thread, and a response is sent.
4. Jetty Continuations Example
4.1 Continuations API
Continuation instance is created with Continuation Support
factory class. Example as below
Continuation cont = ContinuationSupport.getContinuation(request);
continuation.suspend()
suspends a request. The request will be suspended until either continuation.complete()
or continuation.resume()
is called. If none of those are called, continuation will timeout after a default time period.
Once a continuation is resumed, the request is dispatched to the servlet container.
continuation.resume();
A response for a request is returned when complete is called.
continuation.complete();
4.2 Create eclipse project
In this project, we will use continuations API. We will suspend a request using continuations for certain time period and complete it after that time period. Create a new dynamic web project in eclipse ContinuationsExample
as shown below
Create a new servlet ContinuationsExampleServlet in this project.
If there are build issues with the project, you will import servlet-api-3.1.jar file in the project build path. We will add our code in doGet
method.
ContinuationExampleServlet.java
package com.javacodegeeks.example; import java.io.IOException; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.ContinuationSupport; /** * Servlet implementation class ContinuationsExampleServlet */ public class ContinuationsExampleServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * Default constructor. */ public ContinuationsExampleServlet() { // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestId = request.getParameter("id"); Continuation cont = ContinuationSupport.getContinuation(request); response.setContentType("text/plain"); response.getWriter().println("Request id is : " + requestId + " start: " + new Date()); cont.setTimeout(3000); cont.suspend(); response.getWriter().println("Request id is : " + requestId + " end: " + new Date()); if(cont.isInitial() != true) { cont.complete(); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
If we run this example, we might run into an error which says IllegalStateException: !asyncSupported
. To resolve the error, in web.xml add following lines
<servlet> <servlet-name>ContinuationsExampleServlet</servlet-name> <servlet-class>com.javacodegeeks.example.ContinuationsExampleServlet</servlet-class> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>ContinuationsExampleServlet</servlet-name> <url-pattern>/ContinuationsExampleServlet</url-pattern> </servlet-mapping>
Once the project is build and exported as a WAR
file into webapps directory, we can start the jetty server again. Now if we start a browser and access http://localhost:8080/ContinuationsExample/ContinuationsExampleServlet
, we will see below output
The output shows that request was suspended for 3 seconds after first call and then it was dispatched again like a new request. Thus, it shows the usability of Continuations API and it is used in many examples like ChatServlet
, QoSFilter
.
5. Conclusion
In this example, we showed how to use Jetty Continuations API. Similar features were added in Servlet 3.0 asynchronous API. Programming with Continuations API allows application to achieve asynchronicity.
6. Download
This was an example of Jetty Continuations.
You can download the full source code of this example here: JettyContinuationsExample