I am trying to learn Spring MVC recently. It seems that i did not understand well the functionalities of @ModelAttribute annotation and HttpSession.
@SessionAttributes({"shoppingCart", "count"})
public class ItemController {
@ModelAttribute("shoppingCart")
public List<Item> createShoppingCart() {
return new ArrayList<Item>();
}
@ModelAttribute("count")
public Integer createCount() {
return 0;
}
@RequestMapping(value="/addToCart/{itemId}", method=RequestMethod.GET)
public ModelAndView addToCart(@PathVariable("itemId") Item item,
@ModelAttribute("shoppingCart") List<Item> shoppingCart, @ModelAttribute("count") Integer count) {
if(item != null) {
shoppingCart.add(item);
count = count + 1;
}
return new ModelAndView(new RedirectView("showAllItems")).addObject("count", count);
}
@RequestMapping(value="/deleteFromCart/{itemId}", method=RequestMethod.GET)
public ModelAndView deleteFromCart(@PathVariable("itemId") Item item,
HttpSession session) {
List<Item> list = (List<Item>) session.getAttribute("shoppingCart");
list.remove(item);
//session.setAttribute("shoppingCart", list);
Integer count = (Integer) session.getAttribute("count");
count = count - 1;
session.setAttribute("count", count);
return new ModelAndView(new RedirectView("showAllItems"));
}
ShoppingCart and count are the session attributes.
The problem is in the deleteFromCart method. I get the count from session, reassign it and overwrite it in session. But i cant see the updated value of count on jsp. However, the updated shoppingCart object can be seen updated, although i do not overwrite the session object (since the object is the same object which is already in session).
But why is the count not updated, although i overwrite it with session.setAttribute? When i add the new count object to the model (model.addObject("count", count)) then i can see the updated value of count. But why does not session.setAttribute give the same result?
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.
Furthermore, there's also an addAttributes() method. Its purpose is to add values in the Model that'll be identified globally. That is, every request to every controller method will return a default value as a response.
@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.
@SessionAttributes annotation is used to store the model attribute in the session. This annotation is used at controller class level. In the above code snippet, the model attribute 'user' will be added to the session if the name attribute of the @ModelAttribute and @SessionAttributes annotations is same.
First of all, @SessionAttribute
does not have to use the http session. It uses a SessionAttributeStore
which can have anything as its backing storage. Only the default implementation uses the http session.
The reason why your code does not work as expected lies in how @SessionAttribute
works.
Before a controller method is invoked, everything listed in @SessionAttributes
, in your case {"warenkorb", "count"}
, is read from the session and added to the model.
After the method has returned the session is updated with everything that has been added to the model within the method.
.addObject("count", count)
-> count is added to the model and afterwards to the session.
session.setAttribute("count", count)
-> count is added to the session but not to the model. It will be added to the model before the next invocation of any controller method. But as for now the model still has the old count
. And the model is what gets added to the request. And if an attribute can be found in the request scope then the jsp does not care about what's in the session.
When you use @SessionAttributes
and @ModelAttribute
(or Spring MVC in general) then avoid using HttpSession
or HttpRequest
. Even HttpResponse
is of limited use. Embrace the beauty of Spring MVC
instead :)
model.addObject
puts object to the request scope while HTTPsession.setAttribute
puts it to the session scope. And since variables on jsp are resolved on the next order: page scope -> request scope -> session scope -> application scope, you get what you get.
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