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
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.
@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.
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.
@SessionAttributes annotation is used to store the model attribute in the session. This annotation is used at controller class level.
@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>
Upon the initial request /sessionattr/init
the view renders as follows
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
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With