I've found this interesting "mal functioning" in a application where I just copied the mapping portion of web.xml for a new created servlet, but forgot to change de URI. Tomcat deployed the application without any warning, but when running the application only the last referenced servlet was working (like if the mapping of the first has been overwritten by the last in the XML file). I made additional tests using annotations in servlets, and the behavior of having more than one servlet with same mapping causes random access to one or another (I cannot determine a predictable way). In order to prevent breaking existing applications, I would like to have just a "big warning" in the log at startup and/or deployment of the application that have more than one servlet mapped to same URL. Examples of the problem: Example 1: Web.xml ... <servlet> <servlet-name>PrintDacteServlet</servlet-name> <servlet-class>br.com.simfreteV1.web.PrintDacteServlet</servlet-class> </servlet> <servlet> <servlet-name>CotacaoReportServlet</servlet-name> <servlet-class>br.com.simfreteV1.web.CotacaoReportServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>PrintDacteServlet</servlet-name> <url-pattern>/secure/relatorios/Action</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CotacaoReportServlet</servlet-name> <url-pattern>/secure/relatorios/Action</url-pattern> </servlet-mapping> ... Example 2: annotations in java servlet files @WebServlet(name = "PdfReportPrint", urlPatterns = {"/secure/relatorios/doReport"}) public class PdfReportPrint extends AbstractBaseServlet { ... @WebServlet(name = "PrintBoletoServlet", urlPatterns = {"/secure/relatorios/doReport"}) public class PrintBoletoServlet extends HttpServlet { ...
Hmm. Before we do anything on this I'd like to get some feedback from the Servlet EG as to what the expected behaviour is here. My personal view is that it should not be allowed and the web application should fail to start. http://java.net/jira/browse/SERVLET_SPEC-53
The EG has confirmed that deployment should fail.
This has been fixed in trunk and 7.0.x and will be included in 7.0.35 onwards.
Hi Mark, I totally agree with the fact that an URL should be mapped to only one Servlet. But, I'd like to have your point of view and maybe the one of the Servlet EG about the following case. Let's imagine that we have a Servlet annotated with @WebServlet("/an/url") and a web.xml descriptor that define the same Servlet class with a different logical name mapped to the same URL through a Servlet mapping. From my point of view this is actually the "same" Servlet which is mapped to this URL and it doesn't contradict the updated paragraph in the Servlet specification [1]. With the current Tomcat implementation this case will lead to a deployment failure. My proposed solution is that when different Servlet names with the same Servlet class are mapped to a same URL the first one defined will be chosen. This will lead to prefer the one defined in the web descriptor over annotations. So, what do you think? Thanks & regards, Loïc [1] "If the effective web.xml (after merging information from fragments and annotations) contains any url-patterns that are mapped to multiple servlets then the deployment must fail."
My understanding is that Scenario 1: ServletA -> /my/path/to/servlet ServletB -> /my/path/to/servlet Rule: same path to different servlets = failure. Scenario 2: ServletA -> /my/path/to/servlet1 ServletA -> /my/path/to/servlet2 Rule: same servlet to different paths: success. Regards, Edson
(In reply to comment #4) > > Let's imagine that we have a Servlet annotated with @WebServlet("/an/url") > and a web.xml descriptor that define the same Servlet class with a different > logical name mapped to the same URL through a Servlet mapping. > In Servlet Spec 3.0, 8.1.1 @WebServlet There is an explicit statement that these are two different servlets. " If the same servlet class is declared in the deployment descriptor under a different name, a new instance of the servlet MUST be instantiated. " Regards Violeta
Hi Violeta, thank you for that clarification, I agree with you. I missed this statement in the specification. Thanks again. Regards, Loïc
I want to understand more.. having following configuration in deployment descriptor <servlet> <servlet-name>sn1</servlet-name> <servlet-class>com.servlets.urlpatterns.Servlet1</servlet-class> </servlet> <servlet-mapping> <servlet-name>sn1</servlet-name> <url-pattern>/s</url-pattern> </servlet-mapping> <servlet> <servlet-name>sn2</servlet-name> <servlet-class>com.servlets.urlpatterns.Servlet1</servlet-class> </servlet> <servlet-mapping> <servlet-name>sn2</servlet-name> <url-pattern>/s</url-pattern> </servlet-mapping> why should the server startup / app deployment fail? what makes the difference? Any how both the servlets sn1 and sn2 are referring to same Servlet1
(In reply to Abdul Aziz from comment #8) > > Any how both the servlets sn1 and sn2 are referring to same Servlet1 Once you use <servlet-class>com.servlets.urlpatterns.Servlet1</servlet-class> the servlets will point to one and the same class. But you need to specify different url-patterns that's the case.
(In reply to Violeta Georgieva from comment #9) > (In reply to Abdul Aziz from comment #8) > > > > Any how both the servlets sn1 and sn2 are referring to same Servlet1 > > Once you use > <servlet-class>com.servlets.urlpatterns.Servlet1</servlet-class> > the servlets will point to one and the same class. > > But you need to specify different url-patterns that's the case. Correct!! My Question is, Why should the server start-up fail? What difference would it make if I try to access either of the servlet's with same url pattern? I agree its foolish doing so.. But failure during server up doesn't make sense, Right? Earlier versions of Tomcat used to support this (prior to 7.0.35) However server start-up should fail, if same url pattern refers to different servlets say <servlet> <servlet-name>sn1</servlet-name> <servlet-class>com.servlets.urlpatterns.Servlet1</servlet-class> </servlet> <servlet-mapping> <servlet-name>sn1</servlet-name> <url-pattern>/s</url-pattern> </servlet-mapping> <servlet> <servlet-name>sn2</servlet-name> <servlet-class>com.servlets.urlpatterns.Servlet2</servlet-class> </servlet> <servlet-mapping> <servlet-name>sn2</servlet-name> <url-pattern>/s</url-pattern> </servlet-mapping>