The annotation @SessionAttributes is used on class level. Typically it's used on the @Controller class. It's 'value' element is of type String[] whose values are the matching names used in @ModelAttribute either on method level or on handler's method parameter level.
Let's consider following arrangement:
@Controller @SessionAttributes("visitor") @RequestMapping("/trades") public class TradeController { @ModelAttribute("visitor") public Visitor getVisitor (....) { return new Visitor(....); } .... }
In above code, when a request comes in, the first thing Spring will do is to notice @SessionAttributes('visitor') and then attempt to find the value of 'visitor' in javax.servlet.http.HttpSession. If it doesn't find the value, then the method with @ModelAttribute having the same name 'visitor' (method getVisitor()) will be invoked. The returned value from such method will be used to populate the session with name 'visitor'.
Now that 'visitor' with it's value is already in HttpSession, let's consider following arrangement:
@Controller @SessionAttributes("visitor") @RequestMapping("/trades") public class TradeController { @RequestMapping("/**") public String handleRequestById (@ModelAttribute("visitor") Visitor visitor, Model model, HttpServletRequest request) { model.addAttribute("msg", "trades request, serving page " + request.getRequestURI()); visitor.addPageVisited(request.getRequestURI()); return "traders-page"; } ....... }
On finding @ModelAttribute("visitor") in the target handler method, Spring will retrieve the value of 'visitor' from the session and will assign the value to the Visitor parameter and will invoke the method. At this step, Spring doesn't care how the session was populated with 'visitor', Whether it was populated using the last arrangement or some other way, it doesn't matter, Spring only requires the annotation @SessionAttributes('visitor'), the handler method parameter with @ModelAttribute("visitor") and the value of 'visitor' in HttpSession. If spring can't find it in the session and last arrangement is not available then following exception will be thrown:
org.springframework.web.HttpSessionRequiredException: Expected session attribute 'visitor'
In other words: when the target handler method is invoked first time in a given session, then method with @ModelAttribute('visitor) is invoked, the returned value is populated in HttpSession and the handler method with the same value is invoked. For the subsequent requests within the same HTTPSession, Spring retrieves the same object from the session and doesn't call the method with @ModelAttribute('visitor') again till the end of the session
Following is the complete controller class:
@Controller @SessionAttributes("visitor") @RequestMapping("/trades") public class TradeController { @RequestMapping("/**") public String handleRequestById (@ModelAttribute("visitor") Visitor visitor, Model model, HttpServletRequest request) { model.addAttribute("msg", "trades request, serving page " + request.getRequestURI()); visitor.addPageVisited(request.getRequestURI()); return "traders-page"; } @ModelAttribute("visitor") public Visitor getVisitor (HttpServletRequest request) { return new Visitor(request.getRemoteAddr()); } }
In above example we are tracking the user visited pages within the same HTTP session. We are using the wildcard '/**' so that all request starting with 'trades' will map to this controller.