Page 1 of 4 123 ... LastLast
Results 1 to 10 of 33

Thread: Controller picks up call to ViewResolver

  1. #1
    Join Date
    Jan 2006
    Location
    Rotterdam, Netherlands
    Posts
    17

    Default Controller picks up call to ViewResolver

    Hello,

    I have exactly 1 Controller that I want to pick up any request. Since I want to put information in the URL (as opposed to parameters), and I want to be able to start this info from the root (eg http://hostname/info/moreinfo/...), I came up with the following mapping:

    Code:
    <bean name="showCategoryController" class="favorites.www.ShowCategoryController">
    	<property name="bookmarkService" ref="bookmarkService"/>
    </bean>
    	
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    	<property name="mappings">
    		<props>
    			<prop key="/*">showCategoryController</prop>
    		</props>
    	</property>
    </bean>
    	
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="prefix">
    		<value>/WEB-INF/jsp/</value>
    	</property>
    	<property name="suffix">
    		<value>.jsp</value>
    	</property>
    	<property name="viewClass">
    		<value>org.springframework.web.servlet.view.JstlView</value>
    	</property>
    </bean>
    The problem is, that when I want to show a View, it is again picked up by the Controller (since it matches /*). How can I avoid this? Is this behaviour at all desirable? I would think that by the time you decide to show a View, you are beyond matching Controllers.

    Jeroen
    Last edited by Jeroen Kransen; Feb 3rd, 2006 at 07:50 AM.

  2. #2
    Join Date
    Aug 2004
    Location
    London, UK
    Posts
    339

    Default

    what do you mean "when I want to show a view" ? Are you trying to reference a JSP directly from a URL and bypass the controller?

    Regards,
    Darren Davison.
    Public Key: 0xE855B3EA

  3. #3
    Join Date
    Jan 2006
    Location
    Rotterdam, Netherlands
    Posts
    17

    Default

    I am not trying to reference it "directly", as in "from the browser". I let the controller decide to show a view (implemented as a JSP), and then the very same controller picks it up a second time.

    In the given example I referenced a JSP using the InternalResourceViewResolver. This turns out to be the problem. It works (it is not picked up by the controller) when I use for example the VelocityViewResolver. So now I am using Velocity, which isn't that bad either, but it's a bit funny that I can't use JSPs with JSTL for this reason. Or is there a way to use JSP/JSTL without the InternalResourceViewResolver? Do you agree with me that it's undesired or even incorrect behaviour that calls to InternalResourceViewResolver are picked up (again) by the controller? At least the choice of view technology is obviously not transparent here. I can understand that it is caused by the underlying servlet code and that it's not easy to change this, though.
    Last edited by Jeroen Kransen; Feb 3rd, 2006 at 08:02 AM.

  4. #4

    Default

    Quote Originally Posted by Jeroen Kransen
    I would think that by the time you decide to show a View, you are beyond matching Controllers.
    Yes, you are.

    If I understand what you're saying, you're describing describing something that shouldn't (and if done correctly can't) happen. However, you can't expect anyone to find out what you're doing wrong unless you post some more code, particularly the controller code.

    Some guesses/points/questions:
    1. What output are you getting, which makes you think that calls to InternalResourceViewResolver are picked up again by the controller?
    2. Are you creating a RedirectView (or prefixing the logical view-name with "redirect:") in the controller?
    3. VelocityViewResolver is derived from UrlBasedViewResolver in much the same way as InternalResourceViewResolver, so I don't see why they should act differently in the way you describe.
    Last edited by martinl; Feb 3rd, 2006 at 08:11 AM.

  5. #5
    Join Date
    Jan 2006
    Location
    Rotterdam, Netherlands
    Posts
    17

    Default

    Quote Originally Posted by martinl
    However, you can't expect anyone to find out what you're doing wrong unless you post some more code, particularly the controller code.
    I decided to filter the code to what was relevant here, to not scare people off. It doesn't really matter what the controller does, but let's show some of it here:
    Code:
    String currentPath = request.getRequestURI();
    
    log.debug("current path: "+currentPath);
    
    return new ModelAndView("category-contents", model);
    Quote Originally Posted by martinl
    1. What output are you getting, which makes you think that calls to InternalResourceViewResolver are picked up again by the controller?
    From the log statement above, When I use the InternalResourceViewResolver I get 2 logs from 1 single HTTP request (without redirect), the second is like /WEB-INF/jsp/category-contents.jsp (the view I was trying to show from the first call). When I use VelocityViewResolver, there is only 1 log statement.

    Quote Originally Posted by martinl
    2. Are you creating a RedirectView (or prefixing the logical view-name with "redirect:") in the controller?
    No I don't.

    Quote Originally Posted by martinl
    3. VelocityViewResolver is derived from UrlBasedViewResolver in much the same way as InternalResourceViewResolver, so I don't see why they should act differently in the way you describe.
    Exactly, that's my point.

  6. #6

    Default

    Hm... Well, a VelocityView doesn't call RequestDispatcher.forward(), like an InternalResourceView does when rendering itself, so that may explain the differing behaviour. Does the RequestDispacher's path argument indeed get parsed by the servlet engine, and thus Spring's DispatcherServlet as if it was an ordinary web-request? (I don't know the internals of the Servlet API well enough to know this.) If so, that explains why your Controller with key="/*" get passed a new request after the forward() method is called.

    How about mapping your controller like this instead:
    <prop key="/urlToController**">showCategoryController</prop>

    SimpleUrlHandlerMapping uses an AntPathMatcher by default, so the **'s would match the URL even if it contains slashes, but it would't match the view request.
    Last edited by martinl; Feb 6th, 2006 at 10:12 PM.

  7. #7

    Default

    i have this problem too, and the solution described above is a pretty poor one, in my opinion.

    background - as it says in the spring docs "For view tehcnologies such as JSPs that are actually processed via the Servlet/JSP engine, this is normally handled via InternalResourceViewResolver/InternalResourceView which will ultimately end up issuing an internal forward or include, via the Servlet API's RequestDispatcher.forward() or RequestDispatcher.include()" - that means that the request ends up being caught again by the controller.

    the reason a /* controller is useful is that it allows very clean urls to be exposed to the user. adding a path prefix or file extension removes this problem, but makes the url ugly. i want my users to be able to go to http://example.com/action - why on earth does spring's implementation force that to be http://example.com/something/action or http://example.com/action.html ?!

    i'm amazed there's no good solution for this....

  8. #8

  9. #9

    Default

    So the question is: Is there a way to forward view handling to the .jsp file without using RequestDispatcher.forward() (or include())? If not, the problem is more an issue with the Servlet API than Spring.

    Perhaps Spring could use a HandlerMapping- and/or a PathMatcher-implementation that provides an "all except"-mapping. The "all except"-mappings would be matched only after all regular mappings have been searched without result, and could be configured like this (mapping all requests except the ones ending in .jsp to a controller):

    <property key="!/*.jsp">controllerName</property>

    In fact, what stops you or Jeroen from making your own implementation(s) that does something like this? After all, SimpleUrlHandlerMapping and AntPathMatcher are just "good starts" provided by Spring, not holy grails in and of themselves. I suppose extensibility is one of the reasons we're using an IoC container in the first place.

  10. #10

    Default

    would that work? i was thinking something similar, but thought it had to be at the top level (corresponding to the url-pattern in the web.xml), and as far as i can tell it's not possible to have a "everything but" match there (unless i alter tomcat itself).

    the reason i'm using spring (can't speak for the original poster) is that i find it amazingly helpful. it's like a library of best practices: i trust its solutions more than something i would dream up myself; i assume the developers have much more experience with servlets than me, too. hence my reluctance to extend it to solve (what i assume is) a common problem (and amazement that this is something i can't find a solution for).

    anyway, maybe i'm misunderstanding, because you said "Is there a way to forward view handling to the .jsp file without using RequestDispatcher.forward [...] ?" and then suggested a "everything but" matcher which, as far as i can tell, is a solution that continues to assume RequestDispatcher.forward is called.

    so could you clarify what you think is happening?

    repeating the problem i see - i thought that the forward was returning control to Tomcat, which was then matching the "/*" (in web.xml) again. if there is a "!*.jsp" matcher in myservlet-config.xml then the servlet as a whole will fail. what happens then? how does that help the jsp page be rendered? am i hopelessly muddled?
    Last edited by andrew cooke; Feb 11th, 2006 at 01:46 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •