|Summary:||global web.xml servlet-mappings are not used when additional mappings are defined in app web.xml|
|Product:||Tomcat 7||Reporter:||James DeFelice <james_defelice>|
|Component:||Catalina||Assignee:||Tomcat Developers Mailing List <dev>|
Description James DeFelice 2011-11-04 16:32:54 UTC
In my application web.xml I define a servlet-mapping for a new extension: <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jss</url-pattern> </servlet-mapping> I have not modified, in any way, the global web.xml file. The application context is loaded just fine, but .jsp files are not handled by the JspServlet (which is declared in global web.xml). The end result being that the JSP source code is served to a web client instead of HTML generated by a compiled jsp class. .jsp files are compiled if I add the following to my web.xml: <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping> However, this seems redundant since that mapping is declared already in the global web.xml file. My expectation was that the global mappings would be merged with the application mappings at deploy time -- which does not seem to be happening in this case.
Comment 1 Mark Thomas 2011-11-04 19:33:10 UTC
The current behaviour is by design. The Servlet specification doesn't cover global defaults but Tomcat's behaviour is line with the rest of the Servlet specification. For example, if mappings are provided for a Servlet in annotations and in the main web.xml they are not additive. Only the ones from the main web.xml are used. The full precedence order is: main web.xml > fragments > annotations > defaults
Comment 2 James DeFelice 2011-11-06 21:29:43 UTC
Servlets defined in global web.xml are inherited by webapp web.xml. New servlets defined in web.xml do not eliminate servlets declared in global web.xml, instead they are merged - this spares the app developer from needing to declare the JspServlet, DefaultServlet, etc. in their webapp web.xml files alongside their proprietary servlet declarations. Mappings defined in global web.xml are also inherited, by default, in the webapp. However, if new mappings are added in web.xml, then global web.xml mappings are dropped. Web developers that want to add new mappings for servlets declared in global web.xml are forced to re-declare the mappings in their webapp web.xml because they are not automatically inherited. Why would the design of servlet declaration inheritance be out of sync with the design of servlet mapping inheritance? Especially since servlet and servlet mapping declarations have such a close relationship? This behavior seems inconsistent at best. I'd like to understand the rationale behind this design decision, and how this does not constitute a design bug.
Comment 3 Konstantin Kolinko 2011-11-06 21:35:05 UTC
WONTFIX There is nothing wrong with redeclaring standard servlets and mappings when you need to customize them. (That was always the case as far as I remember since 5.5).
Comment 4 Mark Thomas 2011-11-08 23:41:16 UTC
To expand on my previous comment... When servlet mappings are overridden (e.g. fragment overrides annotations, or application overrides global) all servlet mappings from the overridden source are dropped. The reason for this is simple. If annotations are used to map a servlet to *.foo but the developer wants to change that to *.bar, there is no way to explicitly remove one or more mappings. Therefore, all overridden mappings are removed. The price that is paid for this is that if a developer wants to add a mapping, they have to specify all the overridden mappings as well. This behaviour has been confirmed as required and correct with the Servlet EG for fragments, annotations and main web.xml. The global defaults just follow this pattern.