The Java EE 6 Web Tier: Servlets Gain Asynchronous Support, Improved Extensibility
Many Java web applications are based on a framework such as Apache's Wicket, Java ServerFaces, Struts or SpringMVC. To use a framework the developer registers the framework's artifacts such as servlets, filters and listeners in the application's web.xml configuration file. This can result in a large, complex descriptor and also mixes up the generic framework XML with that specific to the application. A major goal of the Servlet 3.0 specification was to allow the deployment of servlets, filters and listeners without needing to resort to manual editing of the web.xml deployment descriptor, and to provide a means of breaking the web.xml file into discrete modules. To do this the Servlet 3.0 specification adds annotation based configuration (@WebServlet, @ServletFilter and @WebServletContextListener) making the web.xml file optional, and introduces a new concept of web fragments.
Web fragments can be used to separate framework "boilerplate" XML from the rest of an application's configuration and allow an application to self register. A web fragment must be in a file named web-fragment.xml and can be placed in any location in a web application's classpath, though typically they will be placed in the META-INF directory of the framework's jar file. The XML begins with a <web-fragment> element and can then contain much the same elements as the web.xml descriptor. For example:
<web-fragment> <filter> <filter-name>MyXSSFilter</filter-name> <filter-class> MyXssFilter</filter-class> </filter> <servlet> <servlet-name>myFrameworkServlet</servlet-name> <servlet-class> MyFrameworkServlet</servlet-class> </servlet> <listener> <listener-class> MyFrameworkListener</listener-class> </listener> </web-fragment>
The XML fragments are processed by the container during deployment and the final descriptor is assembled. Since the container is responsible for assembling the web.xml file, a problem could arise if a framework's servlets, listeners and filters need to be invoked in a specific order. To avoid this problem the Servlet 3.0 API supports both absolute and relative ordering of deployment descriptors. You specify absolute ordering using the <absolute-ordering> element in the web.xml file which works as follows: each jar in WEB-INF/lib can be given a name by having a <name> element within a META-INF/web-fragment.xml file. The webapp's WEB-INF/web.xml file can then have an <absolute-ordering> element that lists these fragment names in the order they will be applied, together with an optional <others/> element which can be used to specify if and when unnamed jars are included. Since a deployer can choose to list only trusted jars for deployment this feature prevents any accidental deployments. Furthermore, since an ordering can exclude jars that need not be scanned beyond discovering any web-fragment.xml file, the feature should speed up application deployments. Finally, if you want to prevent self registration in a production environment altogether, you use the element <metadata-complete> in the web.xml file to instruct the web container to look for annotations but not web fragments.
As well as supporting fragments and making use of annotations as an alternative configuration mechanism, Servlet 3.0 provides the ability to plug in shared copies of frameworks such as JAX-WS, JAX-RS and JSF, that are built on top of the web container, using ServletContainerInitializers. These are discovered via the jar services API and can specify a list of types that they handle. Any classes of those types discovered in any jar contained in WEB-INF/lib are passed to the ServletContainerInitializer and it is able to use the same programmatic configuration APIs as ServletContextListeners.
Since the Servlet API was first designed, the approach taken to building web applications has shifted significantly with the widespread use of background HTTP requests to the server and asynchronous web technologies. This family of techniques, generally referred to as Ajax or Web 2.0, has had a significant impact on the traffic profile between Web clients (such as browsers) and Web servers, with the client making many more requests to the server than in a page-by-page model.
The situation can be exacerbated if a server-side process takes a long time to complete, as for example when waiting for a connection from an exhausted JDBC connection pool, or a message from a JMS queue. Waiting within the servlet is highly inefficient since it is a blocking operation that consumes a thread and other limited resources. Servlet 3.0 introduces the ability for asynchronous processing of requests so that the thread may return to the container and perform other tasks. When asynchronous processing begins on the request, another thread or call-back may either generate the response and call complete or dispatch the request so that it may run in the context of the container using the AsyncContext.dispatch method.
Since an asynchronous servlet behaves very differently from a non-asynchronous one, Servlet 3.0 requires you to specify asyncSupported=true to indicate that your servlet supports asynchronous requests. You can also mark a servlet filter as asynchronous. The support for asynchronous processing includes new ServletRequest methods, such as startAsync() which returns an AsyncContext object used to hold the request and response objects that were passed in the call to the method. At this point, the thread that served the original request is available for other operations. In addition, the API introduces a new listener class, AsyncListener, that notifies you when an asynchronous operation is complete or if a timeout occurs. The AsyncContext class includes a complete() method, with which you can commit the response after an asynchronous operation is complete. The AsyncListener class has a dispatch() method that forwards the asynchronous request to the container so that other frameworks such as JSP can generate the response.
As well as introducing a number of new techniques and methods, the Servlet 3.0 specification features a number of smaller enhancements. Amongst them, the HttpServletRequest finally gets inbuilt support for the multipart/form-data MIME type, the Cookie class gets support for "HttpOnly" cookies to avoid certain types of cross-site scripting attacks, and the ServletContext API has been updated to allow servlets and filters to be programmatically added to a context.
Fernando Paris Huertas