polling and session timeout

I wanted to bring up the question at the end of
this thread
. Is there any plan to add session timeouts into Vaadin 7 when polling is being used? (I think the code would be the opposite of the heartbeat checking – instead of looking for a lack of requests, look at all requests except the polling call.) Having session timeouts is a requirement for us.

In v6, we used the Refresher add-on and worked around session timeouts
using the HttpServletRequestListener to push events onto a small stack, pop the ones coming from Refresher, and check the timing on each request.
Now that the listener class isn’t available, I think I can do the same thing using something like a filter in front of the Vaadin servlet to store the latest http request timestamps for a session, and then remove the timestamps in my UI class if the current request is a poll() method, but that will get complicated since there can be more than one tab open.

It would be a lot cleaner to do all of this in the Vaadin servlet where the source of a request is first determined, so was hoping that there was a plan to implement this in an upcoming release. If not, any suggestions about how to achieve this like we did with v6 would be appreciated. Am still finding my way around v7.

Thanks,
Bobby

Wait, no, it’s exactly like the heartbeat stuff. I see that you’re artifically ending sessions already even though the http session hasn’t been expired yet. For instance, if I set ‘session-timeout’ in web.xml to 2 minutes, then set ‘closeIdleSessions’ to true and ‘heartbeatInterval’ to 60 seconds, I see that a session left on its own expires 3 minutes after it was created (this is withoug using polling) – checking this with an HttpSessionListener.

But if I click on anything in the app after 2 minutes (before the session has really expired), I properly get a “Session Expired. Take note of any…” message in the UI. So you’re already doing most of my work for me. If there is any way to ignore polling requests the same way you’re ignoring heartbeat requests in the place where you do session timing, that should fix it. Can someone point me to where that happens in the code?

Thanks,
Bobby

p.s. I know there are complications because a refresh can cause tables to send separate requests back to the server to reload and these requests are not initiated by a user. I hacked around this in v6 by ignoring any requests that came in within X milliseconds of a Refresher request. I know, not perfect.

I think that this workaround should work.
Create OwnVaadinServletService extends VaadinServletService
and in there store old timestamp to the session and close session manually if it is timed out

public void handleRequest(VaadinRequest request, VaadinResponse response) throws ServiceException {
  if(!isHeartbeatRequest(request)){
    UI ui = findUI(request);
    if(ui!=null){
      VaadinSession ses = ui.getSession();
      ses.setAttribute("LastRequestTimestamp", ses.getLastRequestTimestamp());
      if ((System.currentTimeMillis() - ses.getLastRequestTimestamp()) > OWN_SESSION_TIME_OUT_LIMIT) {
        // session timed out
        ses.close();
        handleSessionExpired(request, response);
        return;
      }
    }
  }
  super.handleRequest(request, response);
}

Magic happeds in UI class in there register UI as PollListener and when poll call comes roll LastRequestTimestamp back to the previous value

public class VaadinUI extends UI implements PollListener {
...

protected void init(VaadinRequest request) {
  addPollListener(this);
  ...
}
public void poll(PollEvent event) {
  VaadinSession ses = VaadinSession.getCurrent();
  Long timestamp = (Long) ses.getAttribute("LastRequestTimestamp");
  if (timestamp != null) {
    // set old value back
    ses.setLastRequestTimestamp(timestamp);
  }
} 

What you suggest, extending the Vaadin servlet instead of putting the logic in a filter, would definitely simplify the problem a little. Thank you for that.

The problem for me is that your example uses isHeartbeatRequest(), and Vaadin already ignores heartbeat requests for me with this in web.xml:

        <init-param>
            <param-name>closeIdleSessions</param-name>
            <param-value>true</param-value>
        </init-param>

I can add my own method there, but it gets complicated determining if a current request is a refresh request or, and this is the hard part, a request caused by a refresh. For instance, if a table gets refreshed and makes some followup requests to load data. Since those aren’t caused by user interaction, they need to be ignored in terms of session timeouts.

I worked around the refresh-causes-new-requests issue in Vaadin 6 with a timing hack, but am now hoping to do this a different way and just capture events that I know are based on a user instead of trying to ignore ones I think didn’t come from a user. Am hopeful that
what I describe here
will work, but have hit a snag. That’s what usually happens to my “simple” ideas, heh.

Cheers,
Bobby

I don’t see any simple way to determine the source of the event when I intercept the call at the Service level. This may be easy to fix in Vaadin’s core code by using a different request path prefix like the heartbeat requests use. Filed
https://dev.vaadin.com/ticket/17632
to track this.

In the mean time, will try a more direct version of what I was thinking
in this thread
(the same one mentioned in my last post).

Cheers,
Bobby