Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > Web

Reply
 
Thread Tools Display Modes
  #1  
Old Jan 28th, 2006, 03:27 AM
Jeroen Kransen Jeroen Kransen is offline
Junior Member
 
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.
Reply With Quote
  #2  
Old Feb 3rd, 2006, 07:15 AM
davison davison is offline
Senior Member
Spring Team
 
Join Date: Aug 2004
Location: London, UK
Posts: 335
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
Reply With Quote
  #3  
Old Feb 3rd, 2006, 07:44 AM
Jeroen Kransen Jeroen Kransen is offline
Junior Member
 
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.
Reply With Quote
  #4  
Old Feb 3rd, 2006, 08:06 AM
martinl martinl is offline
Member
 
Join Date: Aug 2005
Posts: 52
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.
Reply With Quote
  #5  
Old Feb 3rd, 2006, 08:34 AM
Jeroen Kransen Jeroen Kransen is offline
Junior Member
 
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.
Reply With Quote
  #6  
Old Feb 6th, 2006, 10:07 PM
martinl martinl is offline
Member
 
Join Date: Aug 2005
Posts: 52
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.
Reply With Quote
  #7  
Old Feb 8th, 2006, 08:08 AM
andrew cooke andrew cooke is offline
Junior Member
 
Join Date: Oct 2005
Posts: 17
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....
Reply With Quote
  #8  
Old Feb 8th, 2006, 08:18 AM
andrew cooke andrew cooke is offline
Junior Member
 
Join Date: Oct 2005
Posts: 17
Default

see also here - http://forum.springframework.org/showthread.php?p=38931
Reply With Quote
  #9  
Old Feb 8th, 2006, 12:58 PM
martinl martinl is offline
Member
 
Join Date: Aug 2005
Posts: 52
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.
Reply With Quote
  #10  
Old Feb 8th, 2006, 01:25 PM
andrew cooke andrew cooke is offline
Junior Member
 
Join Date: Oct 2005
Posts: 17
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.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 08:09 AM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.