Session timeout unrelated to user activity - Vaadin 7.7.10 on Tomcat 8.5.16

Vaadin 7.7.10
Tomcat 8.5.16
Java 1.8.0_91
pushmode: automatic
closeIdleSessions: true

We have had reports of sessions logging out while users are active with the application. This has been frustrating as we can’t seem to track down why Tomcat’s session is not being updated, but figure it’s something to do with the websockets/push not updating Tomcat reliably.

Our app shows a “last sent to server” timestamp that seems to keep current, updating as the user clicks on buttons, checkboxes, etc. This field is updated in our VaadinServlet’s VaadinServletService’s requestEnd() method for all request URLs that don’t contain /HEARTBEAT/ in it.

We also have a “list of active sessions” screen that shows all active sessions including the HttpSession.getCreationTime() and HttpSession.getLastAccessedTime(). While the session information always seems a bit behind, it usually keeps current. However, we do see it sometimes appear as if the last accessed time stops being updated when using simple forms that perhaps have immediate fields, etc. Our “last sent to server” timestamp shows each of these clicks updating it, but the HttpSession.getLastAccessedTime() is not updating.

Is there something about push/websockets or anything else that would cause the HttpSession access time not to update? I don’t think we have a way to update it ourselves as I believe it’s managed by Tomcat itself, but as Tomcat is handling the requests, it’s unclear why they are not tied to the HttpSession.

Anybody have any ideas? Thanks as we have a lot of frustrated users who would love for us to find out what’s going astray.

From the Tomcat mailing list, it seems that websockets are not supposed to update the http session:

“What you are seeing is expected behaviour. This was discussed in the WebSocket EG. The short version is: - WebSocket requests don’t update the session’s last accessed time - you need an HTTP request from the browser to update the session’s last accessed time (and update the expiry time of the browser’s session cookie) - so the application has to do periodic HTTP requests. You can reduce the frequency of these requests by extending the session timeout (remembering you need an HTTP request after this to update the browser’s cookie). You then need to be careful to reduce the timeout again once WebSocket comms end.”

Doesn’t the HEARTBEAT request go over an HTTP(S) GET type request? It is my impression that the heartbeat should occur every 5 minutes, and if it uses HTTP, then it should keep the session alive.

Is it possible that it’s Vaadin ending the session by mistake since we do have the closeIdleSessions set?

Does anybody know if these entries we have in our web.xml are still needed in Vaadin 7.7.10, or perhaps they contribute to issues we see?

[font=courier new]

org.atmosphere.cpr.sessionSupport
true

org.atmosphere.cpr.SessionSupport [/font]

In my test today, I noted that closeIdleSessions=true and heartbeatInterval is 300, and my session-timeout is 60.

Per my web.xml:

heartbeatInterval 300

My servlet has:

    <init-param>
            <description>Want idle sessions to expire, after 3 missed heartbeats, since heartbeat will otherwise keep alive as long as the browser is open</description>
            <param-name>closeIdleSessions</param-name>
            <param-value>true</param-value>
    </init-param>

And session config is:

60 true

Yet it seems that right at the 5 minute point where the HEARTBEAT would come in, the session ends. It’s odd because we don’t see this everywhere, but we do see it on some deployments. Any idea what might be wrong (again Tomcat 8.5.16).

Our UI code does:

public CustomizedSystemMessages getCustomizedSystemMessages() {
    return customizedSystemMessages;
}

public static CustomizedSystemMessages SetupCustomizedSystemMessages(String url) {
    CustomizedSystemMessages csm = new CustomizedSystemMessages();
    csm.setSessionExpiredURL( ServletUtil.appendUrlParam(url, "t", "to") );
    csm.setSessionExpiredNotificationEnabled(true);
    csm.setCommunicationErrorURL( ServletUtil.appendUrlParam(url, "t", "commErr") );
    csm.setCommunicationErrorNotificationEnabled(true);
    csm.setInternalErrorURL( ServletUtil.appendUrlParam(url, "t", "err") );
    csm.setCookiesDisabledURL( ServletUtil.appendUrlParam(url, "t", "err") );
    return csm;
}

void setupCustomizedSystemMessages() {
    HttpSession sess = getHttpSession();
    String url;
    if (sess != null) {
        url = getRequestExternalContextPath() + "/" + standardLogoutUrl + "?min=" + (sess.getMaxInactiveInterval() / 60);
    } else {
        url = getRequestExternalContextPath() + "/" + standardLogoutUrl;
    }
    customizedSystemMessages = SetupCustomizedSystemMessages(url);
    setLogoutURL(url);
}

Is it possible that some browsers have issues with the http-only cookie for session management?

We do use:

60

true

Just wondering if this is somehow precluding (Safari on Mac right now for sure) the browser from being able to correctly maintain the session for browser requests, websockets and whatever Vaadin is doing for the HEARTBEAT requests it sends over https.

I guess this is a “NEVERMIND” grumble because after I cleared the caches in the Safari browser, it no longer failed on the first heartbeat. No idea what Safari had cached, but it apparently was messing with the HTTP/websocket calls in such a way that it seems the first 5 minute heartbeat would cause the session to end in Tomcat (without apparently sending it as we never saw the HEARTBEAT POST in the access logs, but it would occur right after 5 minutes from login when we’d otherwise expect the first heartbeat.