Servlet 3.0 Proposed "Final" Draft
In my December 2008 blog, I strongly criticised the Servlet 3.0 JSR-315 process and the resulting Public Review Draft, describing it as a: "poor document and the product of a discordant expert group (EG) working within a flawed process" and of producing a "Frankenstein monster, cobbled together from eviscerated good ideas and misguided best intentions".
Perhaps because of these harsh words (or more probably in spite of them), JSR-315 has become significantly less discordant and some good technical progress has been made. While I remain somewhat concerned about the process (Eg we have a Proposed Final Draft while some significant issues have yet to be resolved and/or prototyped), I'd like to focus on the improved spirit of the group and highlight some of the technical achievements that have resulted.
JSR-315 has made significant progress on asynchronous servlets. The proposal, identified in my update on the Public Review Draft, to define a specific dispatch type for async requests has been adopted and that has resulted in a very workable asynchronous servlet proposal. Once asynchronous dispatches were separated from normal dispatches, this made irelevent most of the differing opinions about how filters should apply and if forward semantics should apply. As a result the methods previously named AsyncContext.forward(...) have now been renamed to AsyncContext.dispatch(...) and there is general agreement and support of the different asynchronous style of usage possible with this API.
I think the final async proposal is far from perfect and perhaps over
complex, I don't think any of the proposals (including my own) could
perfectly retrofit asynchronous behaviour to the servlet spec. The
benefit of the complexity is that the proposal well supports multiple
asynchronous paradigms and usage styles. Most of my prior complaints
were more about specific usage styles and are thus not so important if
multiple styles are well supported.
Annotations and pluggability
Some of the key new features of servlet 3.0 is the increased support for ease of deployment with new ways to discovery, configure and deploy Filters and Servlets:
- Annotated filters and servlets may be deployed without the need for a web.xml entry.
- Jars may contain /META-INF/web-fragment.xml files with a subset of web.xml configuration.
- Programmatic configuration of Filters and Servlets from ServletContextListeners, which are potentially discovered in /META-INF/*.tld files within jars.
Since the Public Review Draft, an additional feature has been added for automatic discovery of webapplication configuration:
- 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 ServletCotnainerInitializer and it is able to use the same programmatic configuration APIs as ServletContextListeners.
I believe these mechanisms are good improvements in the specification and I support their inclusion. I previously expressed concerns about the flexibility and optionality of their usage. Specifically that:
Accidental Deployment: Web applications can contain many third party jars and that deployers may not be willing to trust all of them to the same degree to be able to deploy and configure arbitrary filters and servlets.
Slow Deployment: Web applications can contain many many jars and that scanning of the classes of all the jars could slow deployments.
Ordering: There was no mechanism to specify ordering, thus limiting the usefulness of the features for modularization.
Parameterization: The configuration baked into a JAR cannot be parameterized, thus unpacking is needed to discover/change default configuration.
The Proposed Final Draft (8.2.2 & 8.2.3) has addressed all but the last of these concerns with the ability to specify in web.xml an absolute ordering of jars within WEB-INF/lib/ that allows jars to be excluded from the ordering. Each jar in WEB-INF/lib may be given a name by having a <name> element within a META-INF/web-fragment.xml file. The webapps WEB-INF/web.xml file can then have an <absolute-ordering> element that lists the fragment names in the order they will be applied, together with the optional <others/> element to specify if and when unnamed jars are included.
As well as my ordering concern, this feature addresses accidental deployment, as a deployer can list only known well trusted jars; and slow deployment, as an ordering can exclude jars that need not be scanned (other than to discover any web-fragment.xml file).
However, my lingering concern is that the PFD as written does not well express that Filters and Servlets cannot be configured by annotations or TLD listeners from jars excluded from the ordering, nor is it clear that ServletContainerInitializers can be excluded in this fashion. For the purposes of avoiding accidental and/or slow deployment, it does not matter which of the mechanisms a jar uses for ease-of-deployment, exclusion should mean exclusion. The responses from the servlet expert group have generally been in agreement with this, but I think the specification needs to be clearer. I have proposed that the following text be added to section 8.2.3:
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 it's 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 ServletContextInitializer is loaded from an excluded jar, it will be ignored.
- Excluded jars are not scanned for classes to be handled by ServletContextInitializers.
If the exclusion of jars from the configuration discovery mechanism is made explicit, then my main concerns will have been addressed. Parametrization will not be addressed, but I think that is something for consideration in 3.1.
Despite being in Proposed Final Draft, I think we are not quiet at the conclusion stage. However excellent progress has been made and work is continuing. I hope that P in the current PFD is significant and that there will be at least one more draft before we are final. There is still a little time to send your own thoughts to to email@example.com.
Sun Microsystems has invited me to participate in their technical session on Servlet 3.0 at Javaone, together with Rajiv Mordani and Jan Leuhe. I'll be presenting a section on the Asynchronous Servlets API and giving a demonstration that uses some ease-of-deployment features to deploy a webapp on glassfish using the Jetty asynchronous HTTP client in a 3.0 asynchronous servlet. The session is TS-3790 "Java™ Servlet 3.0: Empowering Your Web Applications With Async, Extensibility and More" and is scheduled for Tuesday June 02 12:10 PM - 1:10 PM in E134.
See you there!