Singleton and Scope - spring

<bean id="userFacade" class="com.test.facade.UserFacadeImpl">
<property name="userDao" ref="userDao"/>
<property name="currentUser" ref="user"/>
</bean>
<bean id="user" class="com.test.beans.User" scope="session">
<aop:scoped-proxy/>
</bean>
UserDao and user are passed to it - user being a scope and facade a singleton. So any request to userfacade is going to return a same object but user will be different for each session - the concept session inside a singleton confuses me. Can someone explain?

The "scoped proxy" is a transparent wrapper around your User bean. When a method on that proxy is invoked, it will look up the current HttpSession using Spring's thread-local mechanism (called the RequestContextHolder), and then fetch the User object from inside the session's attributes. If none exists in that session, a new one is created and stored in the session. The "real" method on that User is then invoked.
The big caveat with scoped proxies is that the proxy's methods can only be invoked if the scope is "active", e.g. if the currently executing thread is a servlet request.

The instance of User injected into UserFacadeImpl is a proxy which delegates method calls to the actual session-scoped instances of User.
See also:
Proxy pattern

Related

how does scoped proxy works internally in Spring

consider a case when a prototype-scoped bean is injected into a singleton scoped bean,
when we try to access prototype-scoped bean using the singleton-scoped bean, we are returned with the same bean every time i.e. the bean injected at the time of singleton initialization.
if we want to get different instances everytime we use a scoped proxy.
I did not get the concept how this scoped proxy works behind the stage and how it magically gives us a new instance even if the bean is present inside a singleton.
From the Spring documentation:
3.4.4.5. Scoped beans as dependencies
Being able to define a bean scoped to a HTTP request or Session (or indeed a custom scope of your own devising) is all very well, but one of the main value-adds of the Spring IoC container is that it manages not only the instantiation of your objects (beans), but also the wiring up of collaborators (or dependencies). If you want to inject a (for example) HTTP request scoped bean into another bean, you will need to inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object, but that is smart enough to be able to retrieve the real, target object from the relevant scope (for example a HTTP request) and delegate method calls onto the real object.
…
To create such a proxy, you need only to insert a child element into a scoped bean definition (you may also need the CGLIB library on your classpath so that the container can effect class-based proxying; you will also need to be using Appendix A, XML Schema-based configuration). So, just why do you need this element in the definition of beans scoped at the request, session, globalSession and 'insert your custom scope here' level? The reason is best explained by picking apart the following bean definition (please note that the following 'userPreferences' bean definition as it stands is incomplete):
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>

Locking on spring mvc session command object

I hava a spring 4 mvc controller. I am using annotations to handle multiple requests in the same controller. - e.g.
#RequestMapping("/add_dob")
public String addDateOfBirth(.......) {
........
validateDOB(form, result)
........
}
#RequestMapping("/add_address")
public String addAddress(.......) {
........
}
The thing is that I have a session command object (PERSON) and there is a possibility of the command object becoming inconsistent. I tried using
<bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="synchronizeOnSession" value="true" />
</bean>
in the servlet-name.xml spring file but this is causing all requests on the application to be synchronized (I tested by putting Thread.sleep inside the request on which I intend to synchronize and then tried to access the home page). Is there any way by which I can just synchronize on the session command object or on a scope smaller than the entire session?
Thanks
You could use a specific session-scoped bean, e.g. Person:
<bean class="com.xyz.Person" scope="session">
<aop:scoped-proxy/>
</bean>
Or with annotations:
#Bean #Scope("session") #ScopedProxy class Person {...}
You can then #Autowire this bean to your web service class. Spring guarantees that any time you reference it you will receive the object from the current session. See here for more details.

Spring AOP logging for HTTP request

I am trying to log the http request in controller by aop. However, in the aspect code, if I
httpServletRequest.getInputStream()
then the request data will not be able to retrieve in main flow.
So, I created another public method with in the controller which pass in the request string
public String processRequest(String data){...}
and this method is a pointcut for logging the "data".
But the problem is, seems the point cut for this method is not be able to identify by Spring, there is no logging for this method. I need help on this.
Here is the define for the aop
<bean id="myLogger" class="com.my.MyLogger" />
<aop:config>
<aop:aspect id="Log" ref="myLogger">
<aop:around method="log" pointcut="execution(public * com.my.controller.processRequest(..))" />
</aop:aspect>
</aop:config>
Spring AOP by default uses AOP proxies. So your original bean is wrapped with generated proxy bean and all "outside" calls go through the proxy. Internal method calls (within the same bean) bypass proxy.
It's nicely explained here: http://static.springsource.org/spring/docs/2.5.5/reference/aop.html#aop-understanding-aop-proxies

Scope of a Spring-Controller and its instance-variables

Are all controllers in Spring-MVC singletons and are shared among different sessions and requests?
If so, I assume that a class-variable like
public String name;
would be the same for all requests and sessions? So that if User X makes a request and name is being set to Paul, User Z also has Paul as attribute?
In my case I do NOT want that behaviour but wondered if there is a more easier, or more cleaner OOP-way to have session/request-variables then session.getAttribute()/request.getAttribute()
To answer your first question: yes, Spring MVC controllers are singletons by default. An object field will be shared and visible for all requests and all sessions forever.
However without any synchronization you might run into all sorts of concurrency issues (race conditions, visibility). Thus your field should have volatile (and private, by the way) modifier to avoid visibility issues.
Back to your main question: in Spring you can use request- (see 4.5.4.2 Request scope) and session-scoped (see: 4.5.4.3 Session scope) beans. You can inject them to controllers and any other beans (even singletons!), but Spring makes sure each request/session has an independent instance.
Only thing to remember when injecting request- and session-scoped beans into singletons is to wrap them in scoped proxy (example taken from 4.5.4.5 Scoped beans as dependencies):
<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
<!-- instructs the container to proxy the surrounding bean -->
<aop:scoped-proxy/>
</bean>
Yes, controllers in Spring-MVC are singletons. Between multiple requests your class variable get shared and might result into ambiguity.
You can use #Scope("request") annotation above your controller to avoid such ambiguity.

Troubleshooting session-scoped bean with aop:scoped-proxy

In my Spring 3 project I have the following bean definition
<bean name="account" class="sample.model.Account" scope="session">
<aop:scoped-proxy proxy-target-class="true" />
</bean>
CGLib 2.2 is on the class path, so according to the Spring documentation the account bean should be scoped to the http session of a client.
I populate the account bean when a user logs in, if no user is logged in the account bean is null. However, when using two browsers simultaneously to simulate two different http sessions and logging in on the one browser the other browser is also logged in. I interpret this behavior as the account bean not being scoped to the session
Any suggestions on this? Is there a way to check if a CGLib proxy has been created? When I debug the application and inspect the type of the injected account bean at runtime its sample.model.Account. I am not absolutely sure if this finally means that there was no CGLib proxying the cass.
Just set a breakpoint in the constructor, it should hit once per session

Resources