Servlet 3.0 and JSP 2.2

The Servlet 3.0 specification and JSP 2.2 are both part of Java Enterprise Edition 6. Both offer many new features and improvments over the previous version. Each is discussed below in separate sections.

Introduction to Servlet 3.0

The Servlet 3.0 specification offers several new features. This section explores each feature and provides simple examples to help developers get started migrating from Servlet 2.5. The improvements of Servlet 3.0 facilitate better scalabilty, and better API definitions to increase protability between Servlet containers.

Asnychronous request/response support for time independent processing and event driven processing provides options for further scalability for web applications with long-lived exchanges

Improved security API and annotations

Improved session cookie handling

Annotations simplify development and deployment tasks

Shared libraries improve application portability between containers

Each of the sections isolates an area of the specification that effects servlet development. The examples are simple and are meant to make starting development of a Servlet 3.0 based web application easier.

Annotations Simplify Development Tasks

Servlet 3.0 annotations make servlet development easier because it frees a team of developers from dependence on a single web.xml or a shared fragment. The processing of annotations is controlled in two ways:

All classes using annotations must be in WEB-INF/classes or in a JAR file in WEB-INF/lib

The web-app element of the web.xml contains the metadata-complete attribute. To process annotations metadata-complete must be false. Annotations will be ignored otherwise. The default value of metadata-complete is false which enables processing for both annotations and web fragments.

@WebServlet defines the servlet, the servlet mapping, and servlet configuration.

WebServlet annotated classes must extend HttpServlet

The urlPatterns or value attributes are required. These are mutually exclusive and therefore setting both in the same annotation is illegal.

An annotated servlet must specify at least one URL

If a servlet has been programmatically added, and an annotation that defines the same servlet the values in the annotation will be ignored and new servlet instance with the same name will be created.

The following example creates a servlet named MyServlet with two URL patterns

See the WebFilter JavaDoc in the Servlet3.0 API for complete listing of WebFilter metadata

@WebListener defines a listener and its configuration. There are several base Listeners. Each Listener class is specific. An implementation must extend one of the following built in abstract listeners:

The three examples above are sufficient to get started. There are several more annotations documented in the Servlet3.0 API JavaDoc and much more information on annotation properties and constraints.

Asynchronous Request Processing

Servlet 3.0 introduces time independent processing. Time indepedence means long-lived requests can be run in the container independent of the causal request. This is very useful when requests initiate long-duration database tasks/queries. In general, the typical asynch dispatched request is handled as follows:

The request goes through the normal pipeline of Filters and Listeners

The servlet processes request params

The servlet issues requests to other external services, waits for locks or semaphores for example.

The servlet returns without generating a response

As resources become available, processing continues using the AsynchContext either on the same thread (serial) or concurrently on multiple threads.

The @WebServlet and @WebFilter annotations use the asyncSupported attribute to indicate a Servlet supports AIO. The default value is false. When the value is "true" asynchronous processing can be started in a separate thread.

There are a few details that are worth mentioning to anyone considering asynchronous request processing.

First, servlet requests can be dispatched from an asynchronous servlet to a synchronous servlet. The synchronous requests must return before the asynchronous servlet can continue processing. Calling ServletRequest.startAsync within a Servlet that does not have asynchSupported="true" will cause an IllegalStateException.

Error handling and reporting during asynchronous request processing is problematic. The container is responsible for any errors that occur in the dispatch method and responds in the following ways:

Each AsyncListener registered on the ServletRequest is called via AsyncListener.onError(AsyncEvent). The cause is available via AsyncEvent.getThrowable().

AsyncListeners can complete processing by calling AsyncContext.complete or can call any of the AsyncContext.dispatch methods. If no Listener in the chain makes the call, the container will dispatch an HTTP 500 error and make the cause available in the RequestDispatcher.ERROR_EXCEPTION attribute.

It is possible for an asynchronous operation to time out. When a time out occurs the container:

Invokes the AsyncListener.onTimeout operation on the Listners registered with the ServletRequest that initiated the async request.

AsyncListeners can complete processing by calling AsyncContext.complete or can call any of the AsyncContext.dispatch methods. If no Listener in the chain makes the call, the container will dispatch an HTTP 500 error and make the cause available in the RequestDispatcher.ERROR_EXCEPTION attribute.