42

I would like to implement a shopping cart with Spring, so I need to save an object Cart ( which has attributes like products, paymentType and deliveryType ) in session. I've tried to create it with bean and attribute "scope" set to "session", but it just doesn't work, should I use some additional annotations in my controller or Cart class? Any example usage would be really helpful :-) Thanks in advance.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
tomaszf
  • 433
  • 1
  • 5
  • 4

4 Answers4

49
@Component
@Scope("session")
public class Cart { .. }

and then

@Inject
private Cart cart;

should work, if it is declared in the web context (dispatcher-servlet.xml). An alternative option is to use the raw session and put your cart object there:

@RequestMapping(..)
public String someControllerMethod(HttpSession session) {
    session.setAttribute(Constants.CART, new Cart());
    ...
    Cart cart = (Cart) session.getAttribute(Constants.CART);
}
Sakib Abrar
  • 161
  • 10
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Yes, "an alternative option" works, but I don't want to use it.When I create an private attribute cart in my controller I get error that "No matching bean found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}". The bean should be defined in applicationContext.xml as ? – tomaszf Apr 05 '12 at 20:12
  • 1
    no. in dispatcher-servlet.xml. Or, as I showed - declared with annotations – Bozho Apr 05 '12 at 20:23
  • Hmm, but when I use annotations, without bean definition in dispatcher-servlet.xml I get the error I paste before, plus when I use annotations and I define bean I just get 404 only with that controller. – tomaszf Apr 05 '12 at 20:41
  • the annotations should be combined with . But xml is also fine – Bozho Apr 05 '12 at 21:29
  • @Bozho - is this will work if we are having multiple items in the cart ? here is my question [link](http://stackoverflow.com/questions/30281843/adding-multiple-records-to-the-cart-using-session-springs) – Suleman khan May 16 '15 at 23:52
  • @Bozho will this work if the "@Component @SessionScope" is on a JPA "@Entity"? – Chris Neve Jul 22 '22 at 09:32
15

If you are injecting the shopping cart directly into your controller, the issue is likely happening because your controller is singleton scoped (by default), which is wider scope than the bean you're injecting. This excellent article gives an overview of four approaches to exactly what you're trying to do: http://richardchesterwood.blogspot.co.uk/2011/03/using-sessions-in-spring-mvc-including.html.

Here's a quick summary of solutions:

  1. Scope the controller to session scope (use @scope("session") on controller level) and just have a shopping cart instance in the controller.
  2. Scope the controller to request and have session-scoped shopping cart injected.
  3. Just use the session directly - kind of messy, IMO.
  4. Use Spring's annotation <aop:scoped-proxy/>.

All of the methods have their pros and cons. I usually go with option 2 or 4. Option 4 is actually pretty simple and is the only approach I have seen documented by Spring.

stephen.hanson
  • 9,014
  • 2
  • 47
  • 53
  • The correct URL is http://richardchesterwood.blogspot.co.uk/2011/03/using-sessions-in-spring-mvc-including.html – Gilead Oct 17 '12 at 15:52
  • Note, with solution #4, don't use final on any method. Do so and that accessor will be singleton, not session scoped as AOP cannot intercept finals. – Joseph Lust Nov 26 '13 at 06:08
4

You just need to add Scope annotation as below with session and proxy mode

@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart implements Serializable{
}

Where ever you need to use shopping cart object, you can autowire it

@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {
    Logger logger = LoggerFactory.getLogger(ShoppingCartServiceImpl.class);


    @Autowired
    ShoppingCart shoppingCart;
}

Disclosure: I have developed a sample project, which uses spring MVC, angularJS and bootstrap that demonstrate Spring Session scope -
https://github.com/dpaani/springmvc-shoppingcart-sample

3

try to autowired HttpSession and spring will injects in a proxy to the HttpSession @Autowired private HttpSession httpSession;

OpacANEBDOUR
  • 89
  • 1
  • 7