Announcement Announcement Module
Collapse
No announcement yet.
URL mapping, why don't I get it? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • URL mapping, why don't I get it?

    This seems trivial, but I am not having any luck trying to discover what I am missing conceptually. This is all within Tomcat 5.5.9 and I am installing the app in webapps/test.

    If I use a suffix based servlet mapping in web.xml of,

    Code:
    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>test</servlet-name>
    	<url-pattern>*.html</url-pattern>
    </servlet-mapping>
    then I have no problems mapping URLs in my test-servlet.xml context using a SimpleURLHandlerMapping bean to anything ending in .html.

    The thing is, I don't want to use suffixed URLs all the time. Obviously there are no restrictions on how I can arrange the mapping and yet, I cannot get things to work and I have been reading a lot of debug logs to try and see what is going wrong. So far, nothing has stood out and the dispatcher is seeing the urlMapping I define.

    An example that won't work, is a straightforward variation of that above but now with a path prefix, rather than a ubiquitous suffix.

    Code:
    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>test</servlet-name>
    	<url-pattern>/foo/*</url-pattern>
    </servlet-mapping>
    with a handler bean configured as

    Code:
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="mappings">
    			<props>
    				<prop key="/foo/hello">defaultController</prop>
    			</props>
    		</property>
    </bean>
    
    <bean id="defaultController" class="test.DefaultController"/>
    When I try to access the given url say,

    http://localhost:8080/test/foo/hello

    [ed. minor edit, typo on the path above]

    I can see in the logs that the url is being passed to the dispatcher servlet, but the servlet logs the following.

    Code:
    15&#58;04&#58;23,514 DEBUG DispatcherServlet,http-8080-Processor23&#58;811 - Testing handler map &#91;[email protected]3c24f&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,514 DEBUG DispatcherServlet,http-8080-Processor23&#58;811 - Testing handler map &#91;[email protected]3c24f&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,515 DEBUG SimpleUrlHandlerMapping,http-8080-Processor23&#58;130 - Looking up handler for &#91;/hello&#93;
    15&#58;04&#58;23,515 DEBUG SimpleUrlHandlerMapping,http-8080-Processor23&#58;130 - Looking up handler for &#91;/hello&#93;
    15&#58;04&#58;23,516 DEBUG DispatcherServlet,http-8080-Processor23&#58;750 - No handler found in getLastModified
    15&#58;04&#58;23,516 DEBUG DispatcherServlet,http-8080-Processor23&#58;750 - No handler found in getLastModified
    15&#58;04&#58;23,517 DEBUG DispatcherServlet,http-8080-Processor23&#58;600 - DispatcherServlet with name 'test' received request for &#91;/test/foo/hello&#93;
    15&#58;04&#58;23,517 DEBUG DispatcherServlet,http-8080-Processor23&#58;600 - DispatcherServlet with name 'test' received request for &#91;/test/foo/hello&#93;
    15&#58;04&#58;23,517 DEBUG DispatcherServlet,http-8080-Processor23&#58;811 - Testing handler map &#91;[email protected]3c24f&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,517 DEBUG DispatcherServlet,http-8080-Processor23&#58;811 - Testing handler map &#91;[email protected]3c24f&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,518 DEBUG SimpleUrlHandlerMapping,http-8080-Processor23&#58;130 - Looking up handler for &#91;/hello&#93;
    15&#58;04&#58;23,518 DEBUG SimpleUrlHandlerMapping,http-8080-Processor23&#58;130 - Looking up handler for &#91;/hello&#93;
    15&#58;04&#58;23,519  WARN PageNotFound,http-8080-Processor23&#58;833 - No mapping for &#91;/test/foo/hello&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,519  WARN PageNotFound,http-8080-Processor23&#58;833 - No mapping for &#91;/test/foo/hello&#93; in DispatcherServlet with name 'test'
    15&#58;04&#58;23,520 DEBUG DispatcherServlet,http-8080-Processor23&#58;409 - Successfully completed request
    15&#58;04&#58;23,520 DEBUG DispatcherServlet,http-8080-Processor23&#58;409 - Successfully completed request
    15&#58;04&#58;23,520 DEBUG XmlWebApplicationContext,http-8080-Processor23&#58;216 - Publishing event in context &#91;WebApplicationContext for namespace 'test-servlet'&#93;&#58; RequestHandledEvent&#58; url=&#91;/test/foo/hello&#93;; time=&#91;3ms&#93;; client=&#91;127.0.0.1&#93;; method=&#91;GET&#93;; servlet=&#91;test&#93;; session=&#91;null&#93;; user=&#91;null&#93;; status=&#91;OK&#93;
    Could anyone shed some light on what I am misunderstanding? I know url mapping has been discussed many times, but I could not find a discussion that enlightened me.

  • #2
    The clue is
    Code:
    Looking up handler for &#91;/hello&#93;
    but you have wired up your controller:
    Code:
    <prop key="/foo/hello">defaultController</prop>
    HTH.

    Comment


    • #3
      I see that, but if you look above, the request was for /foo/hello which is precisely, at least I thought, what I wired up the controller to responding to.

      The request was
      Code:
      http&#58;//localhost/test/foo/hello
      which prompted the log line

      Code:
      DispatcherServlet with name 'test' received request for &#91;/test/foo/hello&#93;
      but then the SimpleURLHandlerMapping logs
      Code:
      SimpleUrlHandlerMapping,http-8080-Processor25&#58;130 - Looking up handler for &#91;/hello&#93;
      and finally the resolution,

      Code:
      PageNotFound,http-8080-Processor25&#58;833 - No mapping for &#91;/test/foo/hello&#93; in DispatcherServlet with name 'test'
      So why did the HandlerMapping drop /foo and only look for /hello? I though the application's path (/test) would be dropped, but

      Comment


      • #4
        Ok, well it seems that this is the default behaviour and I suspect that AlwaysUseFullPath is a property which might stop that behaviour. It seems counter-intuitive to me to drop explicitness by default when all these mappings support pattern matching but then an experienced web developer might tell me this is better.

        I sure wish I had tried that property earlier, but I just didn't think it was correct.

        Comment


        • #5
          Another problem was complicating the deduction.

          It seems a view resolver is also required, or at least a good idea, unless you want your JSP files strewn around on physical copies of what I was treating as purely virtual paths or include path information in their references in calls to ModelAndView.

          Now, to get on with the fun!

          Comment


          • #6
            Having a conversation with myself.

            I thought I would just include one more response in an effort to leave a record if anyone else was to have the same problem.

            I'll take back what I said about the default behaviour being counter-intuitive. Now I see that if my web.xml defines a url-pattern of /app/* and within spring all of the references are simply /main, /view, then I nicely decouple the two details.

            For some reason I was insisting on explicitness, not realizing I was painting myself into a corner.

            Comment


            • #7
              I too find it annoying that all of the Spring examples use a dispatcher mapping of *.htm.

              I'll take back what I said about the default behaviour being counter-intuitive. Now I see that if my web.xml defines a url-pattern of /app/* and within spring all of the references are simply /main, /view, then I nicely decouple the two details.
              Have you considered the situation where you want extension-less URLs, but without having to give them a special subdirectory mapping in web.xml? For example, let's say I want my dispatcher to handle both of these URLs:
              • /mywebapp/users
                /mywebapp/tasks
                /mywebapp/users/23
                /mywebapp/tasks/378

              So I want to be able to see (1) all users, (2) all tasks, (3) a specific user, (4) a specific task. There could be other types of resources too. I just listed two to illustrate the question: how do you map the dispatcher so that it can handle all of these resource types?

              1. You could use multiple servlet-mapping elements, one for each resource type, but then you're doing all your mapping in web.xml, which kills half the benefit of using spring's dispatcher. Even if you did this, you'd still have to combine it with the AlwaysUseFullPath property, or else it still wouldn't work.

              2. Perhaps you could map the dispatcher to / in web.xml, but then how does the dispatcher handle requests for static resources (html, images, etc.)?

              The goal is to not have to add meaningless path info in web.xml, because then you end up with URLs like this:
              • /mywebapp/foo/users
                /mywebapp/foo/tasks
                /mywebapp/foo/users/23
                /mywebapp/foo/tasks/378

              When you use an unnecessary path prefix, all of your HTML output has to reference other static resources using up-level links such as ../staticpage.html, which complicates the HTML considerably.

              Comment

              Working...
              X