views:

2713

answers:

3

I am trying to implement RESTful urls in my Spring MVC application. All is well except for handling form submissions. I need to redirect either back to the original form or to a "success" page.

@Controller
@RequestMapping("/form")
public class MyController {

    @RequestMapping(method = RequestMethod.GET)
    public String setupForm() {
        // do my stuff
        return "myform";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(ModelMap model) {            
        // process form data

        model.addAttribute("notification", "Successfully did it!");
        return "redirect:/form";
    }
}

However as I read in the Spring documentation, if you redirect any parameters will be put into the url. And that doesn't work for me. What would be the most graceful way around this?

A: 

You can have processForm() return a View object instead, and have it return the concrete type RedirectView which has a parameter for setExposeModelAttributes().

When you return a view name prefixed with "redirect:", Spring MVC transforms this to a RedirectView object anyway, it just does so with setExposeModelAttributes to true (which I think is an odd value to default to).

matt b
If the success message isn't exposed as a querystring, how does it get to the redirected view?
JacobM
Thats what I was just wondering.
predhme
How do you want it to get to the success page? If you want to do a redirect, then it seems like you either need to pass it along as a request parameter or you can instead set it in the session and remove it at the next page. But it has to be passed someway.
matt b
Well I can return a ModelAndView with the "/form" as the construct argument. However, this results in the page being a POST request. So that then if they were to refresh the page, it would resend the post request. Not exactly what I would want happening. Thus the redirect. But it does seem that redirect doesn't support this yet. It is set to be modified in 3.1.
predhme
+2  A: 

If you don't want the success message in the URL, then one option is to put it in the session (in the processForm method) and then check for it (and remove it) in the setupForm method.

Edited to add: if this is a pain to do manually, then you could write a subclass of RedirectView that adds a "message" attribute and wraps the process of inserting it into the session. Not sure, though, if there's an easy way to wrap getting the message back out of the session...

Honestly, I don't think there's an easy answer -- the nature of an HTTP redirect is that state isn't carried over; if you want to maintain state anyway, you're stuck with the various usual ways to maintain state in web applications: the session, a cookie, a querystring...

JacobM
Certainly possible, but since my application is much larger than just the one, that becomes quite a pain having to do that for every single form.
predhme
Struts seems to offer something called ActionMessages. I am not entirely sure what it is. Also, with Ruby On Rails, they offer a flash[:notification]. Which is essentially what I am trying to achieve. The flash message is stored until the next action (resulting redirect or what have you). It seems http://www.jroller.com/raible/entry/migrating_from_struts_to_spring attempted to tackle this. His way seems interesting.
predhme
Well, it looks to me like his approach is basically wrapping the session and putting the message in the session, along the lines of what I had in mind. But he gives actual code, so certainly more useful.
JacobM
A: 

http://jira.springframework.org/browse/SPR-6464 provided me with what I needed to get things working until Spring MVC offers the functionality (potentially in the 3.0.2 release). Although I simply implemented the classes they have temporarily and added the filter to my web application context. Works great!

predhme