In order to resolve this impasse, the EG has decided to solicit more community feedback. So this is my biased blog soliciting that feedback. I say biased, because I am a strong advocate FOR some additional flexibility in these new features. I understand that those AGAINST will also be making their case to the community and I will link to them from here once they become available. Thus I’m looking for community support of my views, or corrections to my representations of the situation or just people telling me to chill and to not worry so much about such things.
The requirement given to JSR-315 was to come up with a way to simplify deployment of frameworks and to allow modular or decomposed configuration. There are already some features that partially address this in servlet 2.5, specifically:
- Annotations on servlet classes can be used to add additional configuration to the servlets declared in web.xml: The current support is only for @postConstruct, @preDestroy, @runAs and @resource annotations, but this is the start of decentralized configuration.
- Jar files in WEB-INF/lib are scanned for TLD descriptors that can instantiate Listeners
3.0 Framework Pluggability
- Additional annotations such as @Servlet, @Filter and @FilterMapping have been defined with sufficient parameters (eg urlPattern and initParams) so as to be able to configure filters and servlets entirely from annotations of classes contained within WEB-INF/lib or WEB-INF/classes
- Support for web.xml fragments to be included in the /META-INF directory of jar files within WEB-INF/lib. These web fragments are combined with the web.xml with well defined merging rules (already mostly defined when arbitrary element ordering was supported in 2.5 web.xml)
- Programmatic configuration of Filters and Servlets via new methods on ServletContext. These methods are only active when called from a Listener class defined either in a web.xml fragment or discovered TLD file.
The intent of these features is that a web framework can have all of it’s defaults configuration backed into it’s jar as either annotated servlets, web.xml fragments or as code triggered by a TLD defined listener. Thus it should be possible to simple drop a web framework jar into WEB/INF lib and have that framework available without any editing of the web.xml. It is proposed that these features are turned on by default when a 3.0 web.xml is present or there is no web.xml at all. Some (all?) of these features (at least discovery of annotated servlets) can be turned off by using the meta-data-complete element within a web.xml.
The Automagic Discovery Problems
However I have several significant concerns about the security and flexibility aspects of the automatic discovery mechanism implicit in these proposals:
- Accidental Deployment: Web applications can contain many many third party jars. I have seen several web applications that have over 100 jars that have been pulled in by their frameworks and their dependencies. Other than the performance issue of scanning all these jars at startup, there is a real risk of accidental deployment of features, debugging aids, admin UIs or hacker attacks. The developer/deployers must be aware of all the web features and facilities in all the jars they use! Maintainers that update a jar within a webapp will have to perform due diligence that they are not adding new web features unintentionally. Tools will not be able to greatly assist with this process as the analysis of the programmatic configuration is a NP-complete problem – so you will need to deploy a jar to see what it defines, and even then you don’t know if it may later decide to define new filters and/or servlets.
- All or Nothing:. If there is just 1 servlet defined under WEB-INF that a developer does not want automagically deployed, then there is no mechanism to select included and/or excluded jars. The only options are:
- to modify the jar to remove the unwanted configuration
- to turn off automagic discovery and define every other filter, servlet and listener in web.xml
- let the unwanted servlet deploy and try to block it with security constraints.
- Parameterization: The jars with auto configured frameworks will contain a good default configuration, most probably set up for developer. There is currently no mechanism available to parameterize the configuration within a jar, other than by overriding it in the main web.xml. This will lead either to configuration in two places, configuration cut-and-pasted out of the jar or the all-or-nothing options above.
- Ordering: The ordering of auto discovered configuration has yet to be defined. Ordering is important as this can affect the order of filters and which configuration may be overridden. If the order (when it is defined) is not the desired order, then there is no mechanism to change the order and the all-or-nothing options above will have to be used.
- Disabling: The <meta-data-complete> element will disable automatic scanning for annotations in all jars. It may also disable checking for web.xml fragments (under discussion). But there is currently no mechanism in 3.0 to disable the scanning for TLD listeners with their new capability for deploying arbitrary filters and servlets. Deployment of closed source jars will become an event greater exercise in trust as only decompilation will reveal what may be deployed.
The Proposed Solution
The main idea is to allow web.xml to have optional <include> elements to guide the automagic discovery of configuration. Without a web.xml or with a 3.0 web.xml that does not list any inclusions, the default would be to search all of WEB-INF for annotated servlets and filters, TLD listeners and web.xml fragments as currently proposed. If however, a web.xml contained <include> element, then the discovery process would be modified as the following examples illustrate:
<include src="WEB-INF/lib/dwr.jar"/><include src="WEB-INF/lib/cometd.jar"/><include src="WEB-INF/classes"/>
This include would scan only the dwr.jar and cometd.jar for annotations, TLD fragments and web.xml fragments, the WEB-INF/classes directory would be scanned for annotated servlets. No other jars or classes would be scanned unless listed in their own include elsewhere in the web.xml. The ordering between the includes is well defined, and these element could be placed in the web.xml with other listener/servlet/filter/include declarations before, between or after them.
This include would use the web.xml fragment within the dwr.jar. Similar includes could be used to scan for differently named web.xml fragments and TLD descriptors either within jars or as files within WEB-INF.
Scan the specified class within the DWR jar for servlet or filter annotations. Note that this clause is effectively the same as just a <servlet> or <filter> element, as that would cause the class to be scanned and any annotations for mappings respected. In essence this proposal just extends the current ability to nominate a servlet or filter for auto configuration to jar files, TLD files and web.xml fragments.
<include src="WEB-INF/lib/cometd.jar!dojox/cometd/CometdServlet> <init-param> <param-name>maxIntervalMs/param-name> <param-value>3000</param-value> </init-param></include>
This include element would deploy the annotated CometdServlet from the cometd.jar and would apply the init-param as an override to any default init-params specified in annotations. Similarly init paramters could be set on web.xml fragments or even for listeners discovered in TLD files.
An earlier form of this proposal included wild-card support for the partial URIs passed to the include elements. While this may be useful, it does increase the complexity and I believe the proposal works well enough for most cases without it. A web application with 100 jars is still only likely to include a few web toolkits.
The Case Against?
Due to my declared bias, I am not the best one to make the case against. But I will paraphrase it as best I can and will link to the blogs of others when they become available.
The case against the <include> element is that it is a complexity and confusion that can be done without, because the majority of servlet users are either unconcerned about the possibility of accidental deployment or that they are happy to restrict themselves to business as usual with a single main web.xml.
So I’m debating myself now… I think this is called a straw man.
I don’t see this proposal as complex, specially now that I have removed wild carding. The list of include elements may sometimes be long, it will be far more compact, readable and maintainable than copying all the configuration into a single web.xml.
I do find many servlet users that are very concerned both about security and ease of configuration and would at least like the option to explicitly list which components are auto configured. Please tell me if you are one are one or not!