Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Occasionally, Vaadin does not invalidate session after "Session timeout" message

In my Vaadin application I have an issue when Vaadin does not invalidate session after "Session timeout" message. After getting this message users sometimes are able to click the link or refresh the page and continue working as if they are still being logged in. I use the following parameters:

closeIdleSessions=true
heartbeatInterval=60
session-timeout=15

Last parameter (session-timeout) is also set in context.xml (session-timeout=900) and web.xml (session-config/session-timeout=15) as I didn't get clear from vaadin documentation, is there such a parameter for vaadin servlet or not.

Did anybody face the titular problem?

UPDATE 1: Fixed parameters snippet.

UPDATE 2: SessionDestroyListener.sessionDestroy does not get triggered when Session expired message appears.

UPDATE 3: Previous error appeared because of code mistake. Now SessionDestroyListener.sessionDestroy gets called, but I have no access to HttpSession from given event.

Here is my SessionDestroyListener code (please note the comment in one of if branches):

private static class SynchronizerSessionDestroyListener implements SessionDestroyListener {
    @Override
    public void sessionDestroy(SessionDestroyEvent event) {
        if (event.getSession() != null){
            WrappedSession wrappedSession = event.getSession().getSession();
            if (wrappedSession instanceof WrappedHttpSession){
                WrappedHttpSession wrappedHttpSession = (WrappedHttpSession) wrappedSession;
                HttpSession httpSession = wrappedHttpSession.getHttpSession();
                if (httpSession != null){
                    try {
                        httpSession.invalidate();
                        logger.debug("Session '{}' was invalidated", httpSession.getId());
                    } catch (IllegalStateException e){
                        // do nothing, already invalidated
                        logger.debug("Session '{}' was already invalidated: {}", httpSession.getId(), e.getMessage());
                    }
                } else {
                    logger.warn("Could not invalidate http session for vaadin session: http session is null"); // THIS IS THE BRANCH WHICH IS ACTUALLY GET EXECUTED ON 'SESSION EXPIRED' MESSAGE: event.getSession().getSession() is null!
                }
            } else {
                logger.warn("Could not invalidate http session for vaadin session: event session is not an http session");
            }
        } else {
            logger.warn("Could not invalidate http session for vaadin session: event session is null");
        }
    }
}

Here is how I attach the listener:

public class X extends VaadinServlet {
    // different class members
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        getService().addSessionDestroyListener(new SynchronizerSessionDestroyListener());
    }
}
like image 203
Askar Kalykov Avatar asked Oct 15 '25 06:10

Askar Kalykov


1 Answers

I will try to explain how the session invalidation basically works, maybe this helps (I can't read too much information out of your question):

  • Usually the session will timeout after the specified time inside the session-timeout parameter.
  • BUT you have the take the heartbeat interval into account. If your heartbeat interval is shorter than the session timeout (it usually is), the heartbeat will keep the session alive forever.

  • Thats where the parameter closeIdleSessions is relevant. Setting this parameter to true the browser will not take the heartbeats as a valid request for the timeout, but the last, non-heartbeat request.

  • Second BUT: When will the timeout be recognized? The client-side engine can only recognize this at a heartbeat or if the user takes some action (as in both cases a request to the server is done). By consequence the actual timeout will not occur when the specified timeout has passed, but at the next heartbeat after the timeout.
  • Other situation: after 3 missing heartbeats, the server also closes the session. E.g. if the browser is closed this will cause the session to be invalidated as no heartbeats are sent.

Sample web.xml to explain better:

<context-param>
 <!-- ATTENTION: This value is set in SECONDS -->
 <param-name>heartbeatInterval</param-name>
 <param-value>180</param-value>
</context-param>

<session-config>
  <!-- ATTENTION: This value is set in MINUTES -->
  <session-timeout>4</session-timeout>
</session-config>

<servlet>
    <servlet-name>VaadinServlet</servlet-name>
    <servlet-class>com.example.VaadinServlet</servlet-class>
    <init-param>
      <param-name>closeIdleSessions</param-name>
      <param-value>true</param-value>
    </init-param>
</servlet>

Using the above web.xml the session will timeout after 6 minutes (without user interaction).

Explanation:
the session timeout is set to 4 minutes, but there is no heartbeat at 4 minutes. The next heartbeat will be at 6 minutes. Now the client side engine knows that the session actually timed out and will show the according message.

I am not sure if this is the same process when using Vaadin Push as there we have a continous channel from client to server.

Sources:
Book of Vaadin - 4.8.7. Session Expiration
Book of Vaadin - 4.9.6. Other Servlet Configuration Parameters, Session Timeout After User Inactivity

Additional information:
Upcoming Vaadin 7.6 seems to improve client-server connection stability: Blog Post

like image 59
JDC Avatar answered Oct 17 '25 21:10

JDC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!