Session scoped Spring beans in Tapestry

The new Spring 2.0 introduces 3 new bean scopes useful in developing web applications: request, session & application. Yesterday, I had the opportunity of trying this on my Tapestry 4.0 application. What I needed was letting DAO beans know what user was logged in so that they can add accounting information to the records in the DB. Since this is a separate concern from just storing data I didn’t want to introduce this information in business object properties or pass it through parameter values. The typical thing to do then is to use some kind of thread-local storage. However, why fiddle with the JDK ThreadLocalStorage if Spring can do this for you? So, let’s simply inject a session-scoped bean with the account information in the DAO beans.
Obviously, the actual value of the account name has to be stored in the session as well. The logical place for this in the login page. Tapestry isn’t too fond of working with the http session directly. Luckily, when using session-scoped beans that isn’t necessary. All you need to do is inject the spring bean into the logon page like this:

public abstract String getLogin();

@InjectObject("spring:executionEnvironment")
public abstract ExecutionEnvironment getExecutionEnvironment();

In case you’re wondering, the spring: prefix is contributed by the tapestry-spring module by HLS.
And then after authentication:

getExecutionEnvironment().setCurrentUserId(getLogin());

Together with this fragment in the Spring applicationContext.xml file:

<bean id="executionEnvironment"
      class="....env.SettableExecutionEnvironment"
      scope="session">
<aop:scoped-proxy />
</bean>

As it says in the Spring documentation the aop:scoped-proxy tag is important to avoid that everyone shares the same executionContext bean (and thus also their account name!). Also remember that you’ll also have to include a cglib2 jar in /WEB-INF/lib. This is because an actual class is being proxied, not an interface.

Leave a Reply