PDA

View Full Version : Avoiding addition of request parameters using redirect:


fineman
Feb 7th, 2006, 03:26 PM
I always like to use the redirect on post pattern, so the success view of my SimpleFormController should be a redirectView, or use 'redirect:' . This works fine. However, I am also trying to obey the pattern that all my JSPs are within WEB-INF to avoid exposing them, so all requests are via a controller. Hence my success'view' is actually a controller

Example : After AddController adds a record it redirects to URL for ListController to fetch and display the list with the new record.

In this case, I do not want the behaviour where Spring adds the model contents to the URL - I end up with an ugly URL in the browser, including BindException - in fact, if the above best practices are followed I don't think I understand why Spring adds the model data to the URL. I clearly have misunderstood something - can anyone help me?

manifoldronin
Feb 7th, 2006, 10:42 PM
How are you instantiating the ModelAndView object for the redirection? If you pass the existing model (e.g. the model from the errors) to the constructor, Spring will add whatever in there to the end of the URL.

fineman
Feb 8th, 2006, 03:26 AM
I'm simply using 'redirect:' when defining the view:

setSuccessView("redirect:/listQuotes.view");

jonmor
Feb 8th, 2006, 04:33 AM
I wondered about this myself for a while and then came to the conclusion that it could not logically be otherwise. The redirect means you have a new GET request after the POST. So it can't use information stored with the request object (it's a new request), or pass in the information needed as form parameters (it's a GET, not a POST), ergo it must tack the information on the end of your URL as request parameters. You could, perhaps, store the information 'manually' in the session and retrieve it from the session with your new request. Have you looked at that?

fineman
Feb 8th, 2006, 04:54 AM
Well I don't need any information at all for the URL that is the target of the redirect, and I want clean URLs that can be emailed, bookmarked etc easily. For example, if I want to redirect to a logon controller, I don't want any spurious information added to the logon.do URL.

Maybe I am misusing some concepts here but I don't see a way round it if the views (JSPs) are in WEB-INF thus requiring all requests to go through a controller.

Colin Yates
Feb 8th, 2006, 05:27 AM
This was JIRAd a while ago by me: http://opensource2.atlassian.com/projects/spring/browse/SPR-1294

It is easy enough to write your own View; one that allows specifying which parameters should be included. Have a go; it is quite interesting.

fineman
Feb 8th, 2006, 06:47 AM
Thanks. I'll look into doing that. The most useful would be to not have the errors object added - I see the value of adding other elements of the model, but not the errors.

As ever, the more I learn the more there is to learn!

martinl
Feb 8th, 2006, 02:34 PM
If you don't need any information for the new request, how about using ModelAndView.clear() before redirecting (i.e. before returning the success view)? I guess it depends on what kind of Controller you're using, though.

manifoldronin
Feb 8th, 2006, 04:11 PM
I'm simply using 'redirect:' when defining the view:

setSuccessView("redirect:/listQuotes.view");

If you are not instantiating ModelAndView, I believe Spring's default behavior is to create one with the successView and whatever model it finds in the current errors object. Are you overriding the onSubmit method with only one command parameter? I would try overriding the more complex ones.

fineman
Feb 10th, 2006, 07:20 AM
Solved - by overridding onSubmit(Object command) I get to create my own model as you say, so I can leave it empty. Excellent - thanks everyone for your help.

RayKrueger
Mar 11th, 2006, 10:47 AM
I always use onSubmit(Object command) for that reason as well.

I still don't understand why the default behaviour is to tack the BindExcetion stuff on the url? What is the purpose of it?
Can anyone give an example of why that is needed/valuable?

I'm really just curious what that is for.

Colin Yates
Mar 11th, 2006, 01:52 PM
The Spring bind tags need the BindException to work correctly, so SFC puts that in the model.

The RedirectView simply calls toString() on all the objects in the Model.

Simple as that ;)

SFC cannot (and shouldn't) detect whether you are doing a redirect and then decide to (or not) add the ModelAndView. Likewise it would be ugly for ModelAndView to start looking at the Model and ignoring certain magic parameters.

Take a look at the JIRA I submitted for an elegant (IMO) solution.

manifoldronin
Apr 23rd, 2006, 10:05 PM
I just revisited the JIRA Colin created and voted for it. I have come to realize that even though the controller can prepare the model however it wants before sending the redirect, as discussed earlier in this thread, the problem with that workaround is that it at least partially defeats the purpose of externalizing the view name in most of the form controllers. In other words, a controller would consciously customize the model before sending the view only when it knows the view is a redirecting one.

michaelbaranov
Apr 26th, 2006, 03:16 AM
Hello!

I was just going to post the same question as I noticed this thread. The same little 'prolem' for me. And here is my suggestion: to add another prefix like "redirect-clear:". This will have the same behaviour as the "redirect:" prefix, but will automatically clear the model. I bet it well be in demand! :rolleyes: What do you think?

Michael.

Colin Yates
Apr 26th, 2006, 04:39 AM
Hello!

I was just going to post the same question as I noticed this thread. The same little 'prolem' for me. And here is my suggestion: to add another prefix like "redirect-clear:". This will have the same behaviour as the "redirect:" prefix, but will automatically clear the model. I bet it well be in demand! :rolleyes: What do you think?

Michael.
To be honest, I don't like those prefixes at all, it is (IMO) a leakage of concerns. The controller really shouldn't care about the view.

I do think you are right though that sometimes you just want to ignore the model entirely, but not always. I see the following usecases for redirects, split 50/50 for frequency:

- updated some object and you want to render that object
- the redirect needs to include that object (/user.htm?user=1234)
- updated some object and you want to display a list of all objects
- (/users.htm)

There are of course other usecases; redirecting after logging in etc., but the ones above are the most common (for me) :)

michaelbaranov
Apr 26th, 2006, 06:30 AM
To be honest, I don't like those prefixes at all, it is (IMO) a leakage of concerns. The controller really shouldn't care about the view.

I do think you are right though that sometimes you just want to ignore the model entirely, but not always. I see the following usecases for redirects, split 50/50 for frequency:

- updated some object and you want to render that object
- the redirect needs to include that object (/user.htm?user=1234)
- updated some object and you want to display a list of all objects
- (/users.htm)

There are of course other usecases; redirecting after logging in etc., but the ones above are the most common (for me) :)

IMHO prefixes are not too wrong. For me they come very handy. Well, introducing yet another prefix? Why not if it helps! Actually most of us are pragmatics, not purists ;) And mixing the view name with a little page-flow hint is not a big problem... Again, just for me... A more elegant, easy to use, ideologicaly correct solution would be nice too!!! :)

Colin Yates
Apr 26th, 2006, 06:57 AM
A more elegant, easy to use, ideologicaly correct solution would be nice too!!! :)
There already is: http://www.springframework.org/docs/api/org/springframework/web/servlet/view/RedirectView.html

:)

EndlessWinter
Apr 26th, 2006, 07:33 AM
In some way redirect: prefix is better then RedirectView, because the latter limits views injection to those, which can be redirected to.
For example, with redirect prefix i could use

successView="redirect:home.htm"
or
successView="home"

With RedirectView i can use only:

successView="home.htm"


In fact, i even can cite: "The controller really shouldn't care about the view.". For me it means, i shouldn't care inside controller method, whether i should return RedirectView, or simple view. Lets have it configured :)

Colin Yates
Apr 26th, 2006, 12:25 PM
In some way redirect: prefix is better then RedirectView, because the latter limits views injection to those, which can be redirected to.

I don't think I follow you :)

Assume I have a view which renders a list of users. I typically have one view defined which renders the list of users (userView) and another view defined which redirects to that list of users (redirectUserView). I can parameterise the controller with either of them...

How is one better than the other?


In fact, i even can cite: "The controller really shouldn't care about the view.". For me it means, i shouldn't care inside controller method, whether i should return RedirectView, or simple view. Lets have it configured :)
Again, I am confused as to what you are trying say. When I said "The controller really shouldn't care about the view" I was advocating that the "redirect" prefix was a bad thing.....if you decide to change the view you need to mess around with the controller, which IMO is wrong. As someone suggested earlier; pragmatism blows the whole thing out of the water by pointing out how pedantic my argument is, but still :)

So are you advocating that "redirect" inside the controller is a good or bad thing :)

michaelbaranov
Apr 26th, 2006, 04:43 PM
Yatesco, can you please post a short but meaningful example of how to use RedirectView 'the right way'? It would be a good point to continue the discussion or serve as an example of a 'best practice' solution to the issue (we are yet in a public forum where people search for solutions, right? :) ). Hope it won't take too much effor to provide one...

EndlessWinter
Apr 27th, 2006, 05:47 AM
I was trying to express the following:
While using RedirectView inside controller method, we imply, that the request will be redirected to some url. So, this url must be valid for our application - for example it should end with .htm, if our application can only handle requests which end with .htm.
If we are not using RedirectView, we either can prepend the view name with redirect:, or we can not do this. In the latter case, the view can be some jsp page. Overall, view configuring become more flexible. Isn't it?

Colin Yates
Apr 27th, 2006, 05:52 AM
Yatesco, can you please post a short but meaningful example of how to use RedirectView 'the right way'?
I can show you how I use RedirectView according to my definition of "the right way" :) :)

Quite simple really; I use the following view resolver:


<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundl eViewResolver">
<description>View resolver to convert between view names and actual resources.</description>
<property name="basename"><value>config/views</value></property>
<property name="defaultParentView"><value>defaultView</value></property>
<property name="order" value="1"/>
</bean>


and then say I have a controller which manages adding a new user:


<bean id="addUserController" name="/users/add.htm" class="...">
<property name="formView" value="addUserView"/>
<property name="successView" value="addUserDoneView"/>
</bean>


My controller populates a model which contains the user under the key "newUser".

then in my view.properties:


addUserView.(class)=org.springframework.web.servle t.view.JstlView
addUserView.url=/WEB-INF/jsps/users/add.jsp
addUserDoneView.(class)=org.springframework.web.se rvlet.view.RedirectView
addUserDoneView.contextRelative=true
addUserDoneView.url=/users/list.htm


If I decide at a later date that actually we want to show a congratulatory page before showing the user's list we can simple change the definition of addUserDoneView:


addUserView.(class)=org.springframework.web.servle t.view.JstlView
addUserView.url=/WEB-INF/jsps/users/add.jsp
addUserDoneView.(class)=org.springframework.web.se rvlet.view.JstlView
addUserDoneView.url=/WEB-INF/jsps/users/added.jsp


etc.

Not sure if that is what you wanted?

I was being slightly facetious earlier when I suggested that RedirectView is always the right thing to do because it does arguably struggle with the problem of appending everything in the model to the end of the URL; hence this post.

The point I am trying to make though is that whether the view is a redirect, and where that redirect takes you should be external to the controller.

In the same way, the viewNames should be descriptive of their place in the workflow, *not* their implementation. So rather than "redirectToUsersView" I have a "addUserDoneView".

HTH.

manifoldronin
Apr 27th, 2006, 02:44 PM
The point I am trying to make though is that whether the view is a redirect, and where that redirect takes you should be external to the controller.

In the same way, the viewNames should be descriptive of their place in the workflow, *not* their implementation. So rather than "redirectToUsersView" I have a "addUserDoneView".


I don't know about this one. :) This approach does provide more decoupling, but not because of anything special in RedirectView that "redirect:" does not have - if I remember correctly, a UrlBasedViewResolver resolves "redirect:" to a RedirectView anyway, so there isn't much material difference.

IMHO, the extra decoupling is more likely attributed to the fact that you use ResourceBundleViewResolver, which provides an additional layer of indirection - from "addUserDoneView" to the RedirectView.

Colin Yates
Apr 27th, 2006, 04:24 PM
I don't know about this one. :) This approach does provide more decoupling, but not because of anything special in RedirectView that "redirect:" does not have - if I remember correctly, a UrlBasedViewResolver resolves "redirect:" to a RedirectView anyway, so there isn't much material difference.

Indeed. As mentioned earlier in the posts; I am being *extremely* pedantic :) but having to change the code in the controller to change from using redirect to something else is a bad thing. Maybe my wife is right about me being anally retentive ;) :)


IMHO, the extra decoupling is more likely attributed to the fact that you use ResourceBundleViewResolver, which provides an additional layer of indirection - from "addUserDoneView" to the RedirectView.
Yes. Absolutely. The naming of the view is also very imporant. This does bring me to another point though, that if you *do* have your views explicitly defined then it is even worse having "redirect:" in the controller because you are now spreading the definition in two places.....

If you used a viewResolver which resolved the name->jsp then yeah, I can kinda see why "redirect:" is so useful. On the other hand "redirect:" *and* explicit view definitions are still, I think, a bad thing.

michaelbaranov
Apr 28th, 2006, 02:08 AM
Well, IMHO, since we can (and must) inject the view names into the controllers, the prefix does not matter much: it appears close to the view name, close to view resolution and far from the controller :-)

Colin Yates
Apr 28th, 2006, 03:33 AM
Well, IMHO, since we can (and must) inject the view names into the controllers, the prefix does not matter much: it appears close to the view name, close to view resolution and far from the controller :-)
You are not forced to populate the viewNames; if you override on submit and return a modelAndView it ignores the successView.

I assumed this was the situation we have been talking about where people are doing:
ModelAndView onSubmit(....) {
return new ModelAndView("redirect:/users/list.htm");
}

michaelbaranov
Apr 28th, 2006, 04:02 AM
What about

ModelAndView onSubmit(....) {
return new ModelAndView(getSuccessView());
}

? :)
And the property "successView" is injected a value: "redirect:/users/list.htm"
So don't you agree that the view name and the prefix can be easily kept away from the controller? And if so, the prefix is not a bad thing... :cool:

Colin Yates
Apr 28th, 2006, 04:29 AM
What about

ModelAndView onSubmit(....) {
return new ModelAndView(getSuccessView());
}

? :)
And the property "successView" is injected a value: "redirect:/users/list.htm"
So don't you agree that the view name and the prefix can be easily kept away from the controller? And if so, the prefix is not a bad thing... :cool:
If that is the only place views are defined; then sure (i.e. you are using some url->jsp file mapping). If (as mentioned earlier) you do have your views explicitly defined, then no, I still think it is a bad thing, simply because you are spreading your view definition over two places.

But again, all of this is really *really* academic. Pragmatism (as I believe you mentioned) is really shouting "oh just get on with it" :)

P.S. Not so sure I should use the word academic to mean "pedantic beyond the point of real life concern" when I work in a University :)

Colin Yates
Apr 28th, 2006, 04:31 AM
Just to be clear; I am changing my mind, and I can see that there is a valid (both pragmatically *and* academically) use case for the "redirect" prefix.

I do still maintain (and I don't think anyone has argued) that view *definitions* should be kept out of the controller code.

I didn't want people to think I was only starting to mention it was somehow irrelevant and pedantic simply because I was "loosing" my argument :)

Nice discussion everyone. This, I think, is one of the better examples of open online forums :)

marianogo
Aug 7th, 2007, 11:26 AM
Hi everyone,

Sorry for posting in an old thread, but now i have the same problem.
First , Yatesco I wonder which controller do you use in the example , that you posted before.('coz you didnt put a command nor commandClass).

My issue is that I want to redirect,(acording to bussiness logic) , inside my controller to a URL that call me , less some parameters

ej: i have got this

search.htm?param1=value1&param2=value2

and inside my controller myController.htm
i want to extract param2=value2 , hence I make this

redirect:search.htm?param1=value1

but my surprise is that Spring form this URL

redirect:search.htm?param1=value1&CommandName=commandClass&ValidationClassName=ValidationClass


its much o less , what you were talking about , and i dont want that spring do this.
I tried to make the example of Yatesco, but i couldnt make it work.

thanks in advance.

John60
Aug 7th, 2007, 09:56 PM
Hi, everyone!

I like

response.sendRedirect("list.do");
return null;


What do you think about it?