views:

196

answers:

3

I have two servlets 'ExtensionServlet' and 'PatternServlet' and a static html page. The HTML code is given below.

<html>
    <head>
     <title>
      Resolve servlet ambiguity
     </title>
    </head>
    <body>
     <form action="servlets/form.col" method="POST">
      <input type="submit" value="Goto Servlet">
     </form>
    </body>
</html>

The Deployment descriptor is as follows.

<?xml version="1.0" encoding="ISO-8859-1" ?>   
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
    <servlet>
     <servlet-name>Extension Servlet</servlet-name>
     <servlet-class>ExtensionServlet</servlet-class>  
     <servlet-name>Pattern Servlet</servlet-name>
     <servlet-class>PatternServlet</servlet-class>
    </servlet>
    <servlet-mapping>  
     <servlet-name>Extension Servlet</servlet-name>
     <url-pattern>*.col</url-pattern>
     <servlet-name>Pattern Servlet</servlet-name>
     <url-pattern>/servlets/*</url-pattern>
    </servlet-mapping>
</web-app>

When I click the button in the HTML page it leads to "PatternServlet". If I rearrange the servlet order in the deployment descriptor as below, it goes to "ExtensionServlet"

<?xml version="1.0" encoding="ISO-8859-1" ?>   
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
    <servlet>
     <servlet-name>Pattern Servlet</servlet-name>
     <servlet-class>PatternServlet</servlet-class>
     <servlet-name>Extension Servlet</servlet-name>
     <servlet-class>ExtensionServlet</servlet-class> 
    </servlet>
    <servlet-mapping>   
     <servlet-name>Pattern Servlet</servlet-name>
     <url-pattern>/servlets/*</url-pattern>
     <servlet-name>Extension Servlet</servlet-name>
     <url-pattern>*.col</url-pattern>
    </servlet-mapping>
</web-app>

Can anyone please explain this behavior?

Tomcat 6.0.20 JVM 1.6.0_15-b03

+1  A: 

That doesn't look like a legal deployment descriptor to me. Doesn't the schema require something like this:

<servlet>
    <servlet-name>Extension Servlet</servlet-name>
    <servlet-class>ExtensionServlet</servlet-class>         
</servlet>
<servlet>
    <servlet-name>Pattern Servlet</servlet-name>
    <servlet-class>PatternServlet</servlet-class>
</servlet>
<servlet-mapping>           
    <servlet-name>Extension Servlet</servlet-name>
    <url-pattern>*.col</url-pattern>
</servlet-mapping>           
<servlet-mapping>           
    <servlet-name>Pattern Servlet</servlet-name>
    <url-pattern>/servlets/*</url-pattern>
</servlet-mapping>
McDowell
Yeah. Thanks! my mistake!!
bdhar
+3  A: 

Is your schema a shortening of the following?

<?xml version="1.0" encoding="ISO-8859-1" ?>   
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
    <servlet>
        <servlet-name>Pattern Servlet</servlet-name>
        <servlet-class>PatternServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>Extension Servlet</servlet-name>
        <servlet-class>ExtensionServlet</servlet-class> 
    </servlet>
    <servlet-mapping>                   
        <servlet-name>Pattern Servlet</servlet-name>
        <url-pattern>/servlets/*</url-pattern>
    </servlet-mapping>                   
    <servlet-mapping>                   
        <servlet-name>Extension Servlet</servlet-name>
        <url-pattern>*.col</url-pattern>
    </servlet-mapping>
</web-app>

In your version I think you are defining only one servlet.

When tomcat encounters several definitions that match a request (like in your case), it uses the first one.

David Rabinowitz
Yeah. Thanks! my mistake!!
bdhar
+2  A: 

When Tomcat receives a request, it selects one single servlet for execution using the configured servlet mappings. If the requested URL matches more than one mapping, the best match is selected, ignoring the others.

By specification, path-prefix pattern mappings are preferred over extenstion mappings. This means that, in your example, the mapping on "/servlets/" should win over the one on ".col", and the request should always cause the execution of Pattern servlet. The unexpected behaviour you have when you rearrange the declarations is because your descriptor is not correct, as already pointed out by other answers. Try using a correct descriptor, like the one suggested by David Rabinowitz.

Massimiliano Fliri
Thanks Mr.Fliri. I have corrected my descriptor as well. And, where can I find the spec which gives me information on the selection of servlet mapping and preferences like this?
bdhar