Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring: @SessionAttributes vs HttpSession

What's difference between @SessionAttributes vs HttpSession? Which of the two, keeps for more time an object in the session? In which cases I have to use the one and in which cases the other?

Thanks

like image 908
Alex Avatar asked Nov 28 '14 15:11

Alex


People also ask

What is spring HttpSession?

The HttpSession class type lets us know which implementation (e.g. Servlet Container vs. Spring Session) is being used to manage the HTTP Session state. The HTTP Request count is simply incremented every time a client HTTP Request is made to the HTTP server (e.g. Servlet Container) before the HTTP Session expires.

What is @SessionAttributes in Spring MVC?

@SessionAttribute annotation retrieve the existing attribute from the session. This annotation allows you to tell Spring which of your model attributes will also be copied to HttpSession before rendering the view.

What is the use of HttpSession in Spring MVC?

Use it if two or more Controller methods need to communicate some data. But, using this we can only achieve communication within single controller class. You do not use to read and write from and to the session explicitly if you are using @SessionAttributes.

What is @SessionAttributes?

@SessionAttributes annotation is used to store the model attribute in the session. This annotation is used at controller class level.


1 Answers

@SessionAttributes enables persisting model attributes session between requests, and is meant to be specific per hanlder. The intent was to provide a construct that will be a step close towards implementing a conversation scope (shorter than session, longer than request). The need for conversational scope and why it is not fully available with @SessionAttributes is explained well in this blog.

It enables the automatic storing of the matching model attributes (match is based on the name). The default storage is HttpSession but this can be configured differently also. The docs say

Session attributes as indicated using this annotation correspond to a specific handler's model attributes, getting transparently stored in a conversational session. Those attributes will be removed once the handler indicates completion of its conversational session.

This bit however Those attributes will be removed once the handler indicates completion of its conversational session. does not happen automagically, and it is up to a developer to indicate the exit from the conversation by using setComplete on a SessionStatus instance. Otherwise the models attribute will remain in session, often an undesired side effect.

The easiest way to understand the difference is by observing the scope and the value of the model variable, model variable backed with @SessionAttribute, and the "normal" HttpSession variable.

Take a look at the two simple controllers

@Controller
@SessionAttributes("modelAndSession")
@RequestMapping("/sessionattr")
public class FirstController {
    protected static final String NEXT_VIEW = "next";
    @RequestMapping("/init")
    public String handlingMethod1( Model model, HttpSession session) {
        model.addAttribute(NEXT_VIEW, "/sessionattr/afterinit");
        session.setAttribute("session", "TRUE");
        model.addAttribute("modelAndSession", "TRUE");
        model.addAttribute("model", "TRUE");
        return "index";
    }

    @RequestMapping("/afterinit")
    public String handlingMethod2(SessionStatus status, Model model) {
        model.addAttribute(NEXT_VIEW, "/nosessionattr/init");
        //status.setComplete();
        return "index";
    }

}

the second controller

@Controller
@RequestMapping("/nosessionattr")
public class SecondController {
    protected static final String NEXT_VIEW = "next";
    @RequestMapping("/init")
    public String handlingMethod3(Model model) {
        model.addAttribute(NEXT_VIEW, "/sessionattr/init");
        return "index";
    }
}

and the view that will trigger the flow

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<a href="${next}">Next step ${next}</a>
<hr/>
<table>
     <thead>
          <th>key</th> <th>Request scope</th> <th>Session scope</th>
     </thead>
    <tr>
        <td>model</td> <td>${requestScope.model}</td> <td>${sessionScope.model}</td>
    </tr>
    <tr>
        <td>model and session</td> <td>${requestScope.modelAndSession}</td> <td>${sessionScope.modelAndSession}</td>
    </tr>
    <tr>
        <td>session</td> <td>${requestScope.session}</td> <td>${sessionScope.session}</td>
    </tr>
</table>

The flow

Upon the initial request /sessionattr/init the view renders as follows

enter image description here

so the model variable is available in the request scope, the sessionattribute is available in both the request and the session scope and the "normal" session attribute available only in session scope

On the next request /sessionattr/afterinit the view renders as follows

enter image description here

so the model-only variable is gone, while the @SessionAttribute model attribute is pushed from the session to the model and persisted across requests. The next step will target a second controller /nosessionattr/init, and the view will render as follows

enter image description here

now the @SessionAttribute model object is gone from the model, but since the status.setComplete is not explicitely called it remained in the session as a normal variable

This is a specially confusing scenario as many expect that @SessionAttribute model object should be gone after switching handler, however unless explicitly cleared it remains in the session. Feel free to copy the snippets and investigate further the combination that confuses you

like image 199
Master Slave Avatar answered Oct 19 '22 18:10

Master Slave