Bram Smeets Blog

 

Blog on Spring and DWR. AJAX with Spring made easy!

Scoping in Spring 2.0

Filed under: Java, Spring — Bram Smeets at 10:38 pm on Tuesday, September 12, 2006

For long one of the limitations of Spring has been that it only supports two kinds of lifecycles for its managed beans.
By default all beans managed by Spring are singletons. By adding the singleton="false" attribute to a bean definition this bean will become a prototype which means a new instance will be created each time the bean is injected or looked up.

However, up untill now it was not easily possible to scope your bean definitions either per request or per session. As of version 2.0, Spring offers more advanced scoping of your Spring-managed beans. You can define any arbitrary scope for a bean using a ScopedProxyFactoryBean and a specific scope implementation. When using a scoped bean, a proxy will be created for every reference to the scoped bean. The proxy will determine the actual instance it will point to based on the context in which the bean is called.

Spring comes with two build-in scopes: request scope and session scope, but it is also possible to implement your own scope. When using request scope, each request will obtain its own instance of the scoped bean. In case of session scope, each session will obtain its own instance. Changing values on the bean instance will therefore only be visible in the specific context (either the request or session). In order for the scoping to work, the current request (and therefore the session as well) need to be set on the RequestHolder class. You can either set this manually by using the bind(HttpServletRequest) method, or use one of the convenience classes for this. The latter is the preferred way, as this will also handle unbinding of the current request to avoid memory leaks. The convenience classes are: RequestBindingFilter (a servlet filter) and RequestBindingHandlerInterceptor (a handler interceptor).

Setting up scoping for a target bean is similar to setting up target sources as explained in the previous section. Below is an example of a session scoped business object.

<bean id="sessionScopedBean" class="org.springframework.aop.target.scope.HttpSessionScopedProxyFactoryBean"> <property name="targetBeanName" value="businessObjectTarget"/> <property name="sessionKey" value="sessionKey"/>
</bean>

Note that the target object –”businessObjectTarget” in the example– must be a prototype (so setting the singleton="false" attribute on its definition). This allows the ScopedProxyFactoryBean implementation to create new instances of the target as necessary. See the Javadoc for ScopedProxyFactoryBean and the subclasses you wish to use for information about it’s properties.

Next to the HttpSessionScopedProxyFactoryBean in the above example, Spring also offers a HttpRequestScopedProxyFactoryBean that allows for a request scope. Configuration of this proxy factory bean works similar to the session scoped counterpart:

<bean id="requestScopedBean" class="org.springframework.aop.target.scope.HttpRequestScopedProxyFactoryBean"> <property name="targetBeanName" value="businessObjectTarget"/> <property name="sessionKey" value="sessionKey"/>
</bean>

Note: Public fields of scoped beans will not be proxied and therefore will not be scoped. Only method calls are proxied and will therefore be scoped.

As mentioned earlier, you can also define you own scope, for instance a conversation scope based on some kind of conversation id or a user scope which works using a cookie and persists and retrieves user data based on the cookie id. To get started on implementing your own scope, have a look at the JavaDoc of ScopeMap.

Scope tag

Using the aop namespace in the configuration namespace support, it is possible to apply scoping in a much more easy way by setting the scope attribute of a bean definition. The attribute can either be set to request or session to apply respectively request- or session-scoping of your bean. The following example is identical to the previous example of a request-scoped bean.

<bean id="businessObjectTarget" class="..." scope="request"> <aop:scoped-proxy/>
</bean>

Note that you have to declare the aop:scoped-proxy tag as a nested tag in order to inform the Spring container to create a proxy for the bean. In order for this to work, make sure to add the following namespace to your beans declaration.

xmlns:aop="http://www.springframework.org/schema/aop"

For more information on the new scoping in Spring have a look at the Spring reference manual, which (as usual) gives a more thorough description of the new scoping mechanism. It also provides more information on defining your won custom scopes.

2 Comments »

Comment by Zvika

November 16, 2006 @ 5:20 pm

congrats on Spring 2.0 and the Scoping mechanism!
however, two question do pop to mind:
in case of web clustering, the HttpSession.setAttribute(key, val) needs to be explicitly called in order for the replication to be triggered(or else, state integrity might be jeopardized). does Spring support this not-no-uncommon scenario automatically? Frankly, I can’t see how it can(am I missing something here?). if it doesn’t, this feature is architecturally inadequate, not to say inherently broken.
second, what about the conversational scope? why isn’t there a default implementation, allowing Spring to support Seam-like conversational state management out-of-the-box? why go half way here? was the conversational scoping just too hard to implement? if so, this means that we’re probably bound to stay with Spring’s Stateless object model, which may not be adequate to true OOP applications - or as Gavin King puts it(pardon the blasphemy): ‘I’m a Foo, and I need a Bar. Any Bar will do!’ will not always satisfy the needs of your application.

cheers,

Comment by Jon Alvarado

May 3, 2007 @ 4:10 am

ZVIKA, I doubt that the session scoping mechanism explicitly calls the setAttribute() every time, but I wouldn’t say that makes the implementation inadequate or broken. I would say that if you need an implementation that calls setAttribute() every time to support standard J2EE then you can write that yourself and that is why the door was left open for implementing your own scopes. I believe also that there are session replication technologies which don’t require you to call setAttribute every time such as JBoss cache and Terracotta.

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>