In a recent application, the customer wanted to be able to change session timeout dynamically, without restarting the application.
This being a Seam application, I thought it was going to be quite straight-forward: either add it in the timeout= attribute in pages.xml, or just add it wherever we start a new conversation (conversation timeout is effectively what we were looking for anyway).
But, I was wrong.
For starters, the timeout= attribute does not take an EL expression. You can only have a numeric value there. So much for setting it dynamically.
The other thing is – we never start conversations manually – only with pages.xml directives. And I really didn’t want to change the entire conversation management, or dig into Seam code for that matter.
Some google-searches later and I found the HTTP session listener.
The HTTP session listener is a small class you can configure in web.xml, that captures session creation. It has two methods:
void sessionDestroyed(HttpSessionEvent se)
sessionCreated() is called when a new session is created. All that’s left is setting the required timeout there:
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
session.setMaxInactiveInterval(60); //in seconds
}
This is all very nice when you know the session timeout – but if you know it in advance – what’s the use of adding this listener? Just configure components.xml and be done with it.
Getting the timeout configuration value from a database
In our application we have an ApplicationParameterService Seam component. It exposes a method to fetch a configuration value from the database’s configuration table. Sweet. Let’s use it in the session listener:
public static final int TIMEOUT_ID = 70;
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
ApplicationParameterService applicationParameterService =
(ApplicationParameterService) Component.getInstance( "applicationParameterService" );
String timeout = applicationParameterService.getParameterById( TIMEOUT_ID );
session.setMaxInactiveInterval(60 * Integer.parseInt( timeout ));
}
@Override
public void sessionDestroyed( HttpSessionEvent se) {
}
}
So – in the listener, I ask Seam for the application parameter service, look up the session timeout value, which I get in minutes, and set it (transposed into seconds) on the session. No sweat.
Ah, but a little sweat.
Seam throws an IllegalStateException – No application context. This is a weired Seam phenomenon, where even though the application is running (and in fact, the login page uses the ApplicationParameterService) – there’s no active context at the time that the listener is called.
This can be solved by forcing an application context if there is none:
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
if (!Contexts.isApplicationContextActive()) {
Lifecycle.beginCall();
}
ApplicationParameterService applicationParameterService =
(ApplicationParameterService) Component.getInstance( "applicationParameterService" );
String timeout = applicationParameterService.getParameterById( TIMEOUT_ID );
int timeoutSeconds = 60 * Integer.parseInt( timeout );
session.setMaxInactiveInterval(timeoutSeconds);
}
and that’s it.
To have the listener capture session creation – you need to add it to web.xml. Make sure you keep Seam’s listener as the first one in the listeners list though. Seam needs it this way:
<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<listener>
<listener-class>com.duckranger.TimeoutConfigListener</listener-class>
</listener>
Popularity: 19% [?]
One Response to Setting session timeout dynamically with Seam
Leave a Reply Cancel reply
Recent Comments
- Medovarszki: This post saved my hair from falling out but yeah, I beat my head against the wall now too
- Shehryar: Probably the ebst spring web mvc tutorial I have read, explain everything in great detail. i loved it, this...
- armand: You do not resize the image. You just display it smaller using html tag attributes. It would be nice to...
- COTP: ** Just to clarify, in CakeErrorController.php (the copy in app/Controller/) public function beforeRender() {...
- COTP: For CakePHP 2.0+, you can copy lib/Cake/Controller/CakeErrorC ontroller.php to app/Controller/CakeErrorCon...
- Medovarszki: This post saved my hair from falling out but yeah, I beat my head against the wall now too
Categories
- Android (1)
- appengine (3)
- Be nice to your users (6)
- CakePHP (13)
- General (5)
- Googlemaps (3)
- Java (11)
- javaScript (4)
- jQuery (11)
- Seam (2)
- Security (4)
- Spring MVC (1)
- Spring Webflow (2)
- User Interface (5)
- Wordpress (2)
Archives
- January 2012 (2)
- December 2011 (1)
- July 2011 (2)
- June 2011 (4)
- May 2011 (1)
- December 2010 (3)
- November 2010 (1)
- August 2010 (2)
- July 2010 (2)
- June 2010 (4)
- May 2010 (4)
- April 2010 (5)
- March 2010 (3)

This article was nice, clean and very useful. You have been bookmarked.
I have a question: Does the sentence “Lifecycle.beginCall();” has any secondary effects? I’ve never seen it before.
Thanks!