Java Servlet 3.0 Specification Reaches Proposed Final Draft
A major goal of the Servlet 3.0 specification is to allow the deployment of servlets, filters and listeners without needing to resort to manual editing of an application's web.xml file. New features include:
- Use of annotations for filters and servlets which may be deployed without the need for a web.xml entry.
- Support for "web fragments", through which developers can supply configuration information without requiring the manual editing of the web.xml file. XML fragments are placed in /META-INF/web-fragment.xml and can contain almost all the same elements that the web.xml descriptor uses. The XML fragments are processed by the container during deployment and the final descriptor is assembled.
- Programmatic configuration of filters and servlets from ServletContextListeners, which are potentially discovered in /META-INF/*.tld files within jars.
At the Early Draft Review stage these features proved controversial, with some expert group members concerned that the possible deployment of unintended filters and servlets, either accidentally or as a consequence of deliberate obfuscation, represented a serious security risk. In a highly critical blog expert group member Greg Wilkins described the specification as "a poor document and the product of a discordant expert group (EG) working within a flawed process."
The Proposed Final Draft has addressed the majority of these concerns with the ability to specify an absolute ordering of jars, which also allows individual jar files to be excluded. It 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.
In addition to supporting fragments and use of annotations, one of the requirements the expert group set themselves was 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. The ServletContainerInitializer, added since the public review draft, handles this use case. ServletContainerInitializers 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. Though a welcome addition, the ServletContainerInitializer does throw up a new issue which Wilkins highlights in a follow-up blog post, in that it is not clear if ServletContainerInitializers can be excluded using the absolute ordering mechanism. He proposes a change in wording to clarify this:
" If the web.xml contains an <absolute-ordering> that does not include the <others/> element, then only the jars containing the fragments listed in the ordering will be able to instantiate Filters, Listeners and Servlets using the Annotations and Pluggability features. Specifically:
- The web-fragment.xml of excluded jars is not processed.
- Excluded jars are not scanned for annotated servlets, filters or listeners. However, if a servlet, filter or listener from an excluded jar is listed in web.xml or a non-excluded web-fragment.xml, then its annotations will apply unless otherwise excluded by metadata-complete.
- ServletContextListeners discovered in TLD files of excluded jars are not able to configure filters and servlets using the programmatic APIs. Any attempt to do so will result in an IllegalStateException.
- If a discovered ServletContainerInitializer is loaded from an excluded jar, it will be ignored.
- Excluded jars are not scanned for classes to be handled by ServletContainerInitializers."
As well as these ease of use features, JSR-315 adds support for Asynchronous requests allowing the thread to return to the container and perform other tasks. This too proved controversial as the expert group struggled to make the existing RequestDispatcher handle asynchronous redispatch. The resulting API, which added 20 methods and 3 new interfaces to the specification, was widely criticized for complexity at the public review stage. The Proposed Final Draft defines a specific dispatch type, AsyncContext.dispatch, which is used for asynchronous requests and has simplified the API considerably. The @WebServlet and @WebFilter annotations have an attribute - asyncSupported that is a boolean with a default value of false. When set to true the application can start asynchronous processing in a separate thread by calling startAsync, passing it a reference to the request and response objects, and then exit from the container on the original thread. This means that the response will traverse (in reverse order) the same filters (or filter chain) that were traversed on the way in. When asynchronous processing begins on the request, another thread or callback 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.