Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do SessionAttributes get cleared on GET redirect?

For simplicity's sake, these code snippets will be shortened. The purpose of this is to take a GET parameter, set it on the session, and redirect back to the GET with the url parameter removed. Basically, URI cleanup. If there's a better/simpler way to do this, I would be glad to hear it.

I have a controller defined as such:

@Controller
@RequestMapping("/path/page.xhtml")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@SessionAttributes({ "myParam1", "myParam2" })
public class MyController {

  @RequestMapping(method = RequestMethod.GET, params = { "urlParam2" })
  public String handleUriParam(@RequestParam(value = "urlParam2", required = false)
                               final Long urlParam2,
                               final RedirectAttributes redirs) {
    // at this point, myParam1 is set on the session.
    // now set the param as a flash attrib with the name of the session variable
    redirs.addFlashAttribute("myParam2", urlParam2);
    return "redirect:/path/page.xhtml";
  }

  @RequestMapping(method = RequestMethod.GET, params = {})
  public String doGetStuff(ModelMap model) {
    // do stuff using myParam1 and myParam2.
    // problem is, myParam2 is on the session, but myParam1 is not!
  }

}

Like the code says, somehow myParam1 is being un-set when the redirect happens. I can fix this by passing a ModelMap to the handleUrlParam method and manually adding myParam1 to the flash attributes, but that seems to defeat the purpose in my mind.

Why is the SessionAttribute myParam1 being removed after the redirect?

Is there a better way to pull parameters off the URI and put them on the session?

UPDATE

So it seems that whenever you use RedirectAttributes at all, you must make sure you put any SessionAttributes you want to carry into the redirect on the FlashAttributes or else they will be lost. I imagine this happens because SessionAttributes are pulled off the ModelMap (which is replaced by FlashAttributes when used). Is this a bug in Spring or intentional behavior? If it's intentional, can someone explain why? I thought SessionAttributes were meant to stay on until removed by completion of the conversational session.

Similar StackOverflow post here.

Addendum

In light of the accepted answer provided, I am still stumped as to how I can clear the URI parameters while putting them on the user's session. One option I have considered is to create a wrapper for the semi-primitive objects (java.lang.Integer, java.lang.String) I am trying to store because they will not be placed on the URI string, but this seems hacky to me. If anyone has a better way to accept GET parameters, store them on the user's session, and clear those from the user's address bar (which will require a redirect), I will gladly use it.

like image 667
Andy Avatar asked Jun 13 '13 11:06

Andy


1 Answers

So I was looking around the code and Internet to find out why it does not work.

Spring has two completely separate model maps - one for standard view rendering and the other one when a redirect is issued. This can be observed in ModelAndViewContainer.

Now session attribute persistence is done based on the result from mavContainer#getModel(). For redirect scenarios, this returns the redirect model. Hence whatever you set on the standard Model / ModelMap is lost.

This makes sense when talking about standard model attributes. Model is there mainly to pass objects to views. When using redirects, you are dealing with a completely different situation. You want to transfer objects via HTTP redirect - hence the separated string and flash based model.

However my feeling is that they forgot about session attributes when designing this feature. There are some nice discussion in Spring's Jira, however none of them addresses this specific issue.

So yes... this might be a topic for Spring's Jira. And it might be classified as a bug as this prevents anyone from setting session model attributes when using redirect. Forcing Spring to store your session attribute via RedirectAttributes#addFlashAttribute is IMO a hack and kind of a bug on its own.

like image 120
Pavel Horal Avatar answered Oct 30 '22 08:10

Pavel Horal