views:

507

answers:

3

I have a simple Spring form that gets bound to a form object on post. The http POST handler does some work, and then needs to redirect to a new URL, passing the form data as querystring parameters.

So, assuming I have a form backing object with properties "param1" and "param2", I want to build a string that looks something like this:

redirect:/app/new/page?param1=value;param2=value

Now, Spring will automatically bind values FROM a querystring or a form post into my form object, but I want to GENERATE a querystring with values taken from the form object.

Obviously it's trivial to do this manually but since I'm going to have lots of different form backing objects, is there some built-in facility in Spring to generate a query string from a form object, suitable for building into a URL?

Thanks.

A: 

I think, you should use method setExposeModelAttributes of RedirectView class, but it maybe difficult to get access to this method if you use Spring 3.0 annotations on your controllers.

uthark
Doesn't seem to work... I'm using Annotated controllers, so my controller is just a plain java class, not inheriting from any Spring class.If I create a new RedirectView object and return it from the controller... it doesn't append anything to the URL. I can't see how the RedirectView object would get a reference to the form object - there's no setter or constructor option to pass in my form!
When RedirectView is processed <a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html#renderMergedOutputModel%28java.util.Map,%20javax.servlet.http.HttpServletRequest,%20javax.servlet.http.HttpServletResponse%29">renderMergedOutputModel</a> is called. This method receives your model and renders correct url.
uthark
If I create a new RedirectView it won't have any reference to any model object. And there's no setter to give it a model object. If I call the "render()" method on RedirectView, passing a Map containing my model object, then it just throws an IllegalStateException at runtime.Looks like the framework forgot to include support for doing this when using annotations...
+2  A: 

OK, after some tracing into the Spring source code, I think I have some definitive answers.

1) Manually adding query parameters to a URL that you pass back in a "redirect:..." string is A VERY BAD IDEA. Spring caches the views those urls refer to, so if you specify lots of different parameters, you effectively leak memory by making the cache hold lots of values it doesn't need to.

Note that the PetClinic example code in the Spring distribution does exactly this, and apparently there has been a Jira issue raised to correct it :-)

2) The model object is still held by Spring when the controller returns, and Spring WILL automatically add any values in it onto the URL you specify (as query parameters) - PROVIDED that the model values are plain String or primitive objects. Now, since the form backing object is an Object stored as a single attribute, Spring doesn't do anything with it.

So - from an annotated Controller, the best approach seems to be to add a ModelMap parameter to the handler method. When you're ready to return, do something like this:

Assuming the form backing object "formObject" has been passed as a parameter to the controller handler method (via the ModelAttribute annotation) and has properties "param1" and "param2" that are Strings -

modelMap.clear();
modelMap.addAttribute("param1", formObject.getParam1());
modelMap.addAttribute("param2", formObject.getParam2());
return "redirect:/my/url";

And Spring will issue a redirect to /my/url?param1=value;param2=value

There doesn't appear to be a built-in mechanism (in Spring) to turn a bean into a list of key/value pairs for adding into the map, but if you really need that, the Apache BeanUtils library will do nicely. Of course, you don't want to do this for big objects otherwise you might exceed the allowable length of a URL.

Finding all that out seemed to be much harder than it needed to be :-)

+1  A: 
Map<String, Object> model = new HashMap<String, Object();
model.put("stuff", "here");
ModelAndView mv = new ModelAndView("redirect:/somewhere.htm", model);
return mv;

Produces

http://.../somewhere.htm?stuff=here
javadev101