I'm trying to undestand session beans in Spring. The book I'm reading says, about them, that:
the bean is created when needed and stored in the javax.servlet.http.HttpSession. When the session is destoyed so is the bean instance.
I tried with the following example:
The bean:
package com.at.test.web;
public class Cart {
    public static int dummy = 0;
    public Cart() {
        System.out.println("Cart::<init> with hashCode " + hashCode());
    }
}
The bean definition:
<beans:bean id="cartBean" class="com.at.test.web.Cart" scope="session">
    <apo:scoped-proxy/>
</beans:bean>
The controller:
@Controller
public class HomeController {
    @Autowired 
    private Cart cart;
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(HttpSession session, Model model) {
      System.out.println("Cart is: " + cart.hashCode() 
          + " ; dummy = " + (cart.dummy++) 
          + " (" + cart.getClass().getCanonicalName() + ")" 
          + "; session is: " + session.hashCode());
      return "home.jsp";
  }
}
This is what happens on Tomcat startup:
Cart::<init> with hashCode 970109301
I think Spring need this instance in order to create the CGLIB proxies. Anyway, I'm not that sure.
After the startup, I use two different browsers to have two different HttpSession. The result, when the controller is invoked, is:
Cart is: 578093288 ; dummy = 0 (com.at.test.web.Cart$$EnhancerByCGLIB$$2eb8334f); session is: 1013723725
Cart is: 578093288 ; dummy = 1 (com.at.test.web.Cart$$EnhancerByCGLIB$$2eb8334f); session is: 1060682497
The cart instance seems to be shared between HttpSession-s, but I was expecting two instances of Cart.
The same if I let the bean implements an interface, use annotation-driven approch and component scan:
public interface ICart {}
--
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES)
public class Cart implements ICart {
    public static int dummy = 0;
    public Cart() {
        System.out.println("Cart::<init> with hashCode " + hashCode());
    }
}
Am I missing something? Did I misunderstood the meaning of session bean?
                        
There's a lot of proxying and delegation going on.
This field
where
Cartis session scoped will be proxied as you can see in your logsBut this proxy is not wrapping a
Cartobject. It is wrapping aSimpleBeanTargetSourcewhich takes care of getting aCartbean from theBeanFactory.Your bean definition attaches a
SessionScopeobject which is responsible for checking yourHttpSessionthrough astaticThreadLocalfield inRequestContextHolder. When request is made to get a bean from theBeanFactory, it will delegate the action to theSessionScopeobject which will check theHttpSession, use the one there if it exists or create and register a new one if it doesn't.You don't notice this with your test because
delegates to the
SimpleBeanTargetSourceobject (incorrectly, if you ask me). But if you didyou would see the difference as that actually reaches the underlying
Cartobject.Depending on the scope and proxying strategy you use, all this may be different, but the end goal is still achieved.