Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

When you are optimizing your Seam application you will have to consider HTTP session size, memory consumption (session data is kept on the Java Heap by default in JBoss AS), maximum number of active sessions, session idle timeout, and so on. Your goal is to keep the number of active HTTP sessions down, and the session size small. The following pattern helps you do that.

If your application is a typical web site that allows anonymous visitors, most of your HTTP sessions will be for clients who just came to see what your website is about. Very few of them will actually log-in and interact more closely with your application. So most HTTP sessions could be timed out when idle very quickly, let's say if a client did not browse to the next page in 15 minutes, we can kill the session (in web.xml):

<session-config>
    <session-timeout>15</session-timeout>
</session-config>

Actually, when do anonymous clients need an HTTP session at all? They do not need a session to browse your Seam application. However, they need an HTTP session to submit a JSF form. Let's say a client opens a page of your application, and that page has some kind of Search form, which internally uses a JSf POSTback request when submitted. If the client has been looking at this page for less than 15 minutes, she can still submit the form and the JSF backend will find the stored view in the HTTP session and do its thing. On the other hand, if the client has been idle for longer then 15 minutes and then submits the form a ViewExpiredException will be thrown by JSF which you need to handle in your application.

Adjust the session-timeout in your web.xml configuration accordingly.

What if your website also supports authentication? Then users can login, and they certainly expect a longer session timeout than 15 minutes, in fact some might even expect their session to last the whole day when they authenticate in the morning and don't use the browser again until afternoon.

The following Seam component will automatically extend the HTTP session timeout after a user logs in, and it will reset the timeout to the original value when the user logs out:

@Name("authenticatedSessionExtender")
public class AuthenticatedSessionExtender {

    protected final static String REGULAR_SESSION_MAX_INACTIVE_SECONDS = "regularSessionMaxInactiveInterval";

    @Logger
    Log log;

    @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
    public void onLogin() {

        // Store the regular session timeout value, so we can set it back later on logout
        int regularSessionTimeout = ServletContexts.getInstance().getRequest().getSession().getMaxInactiveInterval();
        Contexts.getSessionContext().set(REGULAR_SESSION_MAX_INACTIVE_SECONDS, regularSessionTimeout);

        // Now get the configured timeout for authenticated users and set it
        ApplicationConfig app = (ApplicationConfig) Component.getInstance(ApplicationConfig.class);
        if (app.getAuthenticatedSessionTimeoutMinutes() != 0) {
            log.debug(
                    "Setting timeout of authenticated user " +
                            "session to minutes: " + app.getAuthenticatedSessionTimeoutMinutes()
            );
            ServletContexts.getInstance().getRequest().getSession().setMaxInactiveInterval(
                    app.getAuthenticatedSessionTimeoutMinutes() * 60
            );
        }
    }

    @Observer(Identity.EVENT_LOGGED_OUT)
    public void onLogout() {

        Object o = Contexts.getSessionContext().get(REGULAR_SESSION_MAX_INACTIVE_SECONDS);

        // Don't rely on that, do a null check - this should never be null but sometimes it is... *sigh*
        if (o != null) {
            int regularSessionTimeout = (Integer) o;
            log.debug("Resetting timeout of user session after logout to minutes: " + regularSessionTimeout / 60);
            ServletContexts.getInstance().getRequest().getSession().setMaxInactiveInterval(regularSessionTimeout);
        } else {
            // Safety if for some reason the REGULAR_SESSION_MAX_INACTIVE_SECONS was not available then
            // reset the timeout to a low value, 10 minutes
            ServletContexts.getInstance().getRequest().getSession().setMaxInactiveInterval(600);
        }
    }
}

This class relies on the (imaginary) method ApplicationConfig.getAuthenticatedSessionTimeoutMinutes(). You can either write that component and provide this method, or you can find another way of configuring the session timeout value for authenticated users. For example, you could just add it as a property of this class and configure it through components.xml.