Search code examples
javaspringsessionsession-statelifecycle

Spring lifecycle issue: the annotation @SessionAttributes makes session attributes live longer than the session itself


here is the code that can reproduce this issue:

@Controller
public class FirstController {
    @RequestMapping(value = "firstpage", method = GET)
    public String myHander(HttpSession httpSession) {
        if (httpSession.getAttribute("someClass") == null) {
            httpSession.setAttribute("someClass", new SomeClass());
        }
        return "firstpage";
    }
}

the first controller puts something in the session if it's not already there.

@Controller
@SessionAttributes(types = SomeClass.class)
public class SecondController {

    @RequestMapping(value = "secondpage", method = GET)
    public String myHandler(SomeClass someClass, HttpSession httpSession) {
        //asking spring for the SomeClass parameter, that's why we put it in the annotation.
        System.out.print(someClass.hashCode());

        httpSession.invalidate();

        return "secondpage";
    }
}

the second controller kills the session.

and in both jsp files, i have the following code that prints the hashcode of the session object and the hashcode of the session attribute:

session hash:
<%= session.hashCode() %>
<br/>
someclass hash:
<%= session.getAttribute("someClass").hashCode() %>

now if i run the application and visit "firstpage", i'll get this:

session hash: 1838367636

someclass hash: 1075505853

and then i visit the "secondpage", and will get this:

session hash: 842656294

someclass hash: 1075505853

we can see that the session itself is changed, because the second controller kills the session. but the session attribute(of the type SomeClass) remains the same.

then if i try to revisit the "secondpage", the session object changes every time, but the session attribute remains the same.

why does the session attribute(which is supposed to be attached to the session) have a longer lifecycle than the session itself?

PS:the complete code is here:https://github.com/cuipengfei/One-hundred-thousand-why/tree/master/20130701SessionAttributesLifeCycle/SpringMVC

you can run it with mvn jetty:run to reproduce the issue.


Solution

  • The documentation for this annotation isn't particularly clear, but my understanding is that it's used to share values between methods in the same controller. As I read the following:

    This will typically list the names of model attributes or types of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans between subsequent requests

    I interpret it to mean that each controller method invocation will be wrapped with a call to (1) load the session attributes before entry, and (2) store them at exit. Which would have the behavior that you're seeing.

    This is reinforced (imo) by the following in the annotation's javadoc:

    For permanent session attributes, e.g. a user authentication object, use the traditional session.setAttribute method instead

    If they're telling you to use the standard functions to modify the session, it indicates to me that the annotation isn't simply a way to access items in the session.

    And for a final data point: if this annotation were the way to manage session data, why have session-scoped beans?