This blog shows an example of manually tracking user requests in order to time out sessions properly. The application is contained in this one class (linked here for reference). You can get the whole application in this zip file that includes pom.xml for building and a session listener to see when sessions start and end.
Note the README file: you have to build with the -Pcompile-widgetset option the first time because we're using a Vaadin add-on. Thank you to this blog for showing me how to put the widget compilation into its own profile!
The code is heavily commented to explain how user activity is tracked, but here is a summary:
- Using the HttpServletRequestListener interface we can note when a request comes in and compare the time of the request to the time of the previous one. If it's been X minutes, end the session.
- But we don't want to note the time of every request. So in step 1 we note the current time, but save the previous one (like pushing the time onto a stack). If the Refresher.RefreshListener is called, we know this isn't user input, so we can discard the current request time and only consider the older one (popping the stack).
- At this point, we can now compare the current request time to the older one and make a decision about ending the session.
This description of the application is also contained in the source code:
Simple app with a label and start button. When a user first loads the
page, there are no automatic refresher calls happening and the container
will timeout the session normally.
Clicking the button starts the refresher, mimicking a user logging into
the 'real' application UI. Whenever the UI is refreshed, it updates
the label with a new value. This represents the UI reading state from
another resource such as a database, which is constantly updated by
other threads. For our simple case, we just show how much time we
have left before ending the session.
The application was deployed and tested on a GlassFish 3.1.2 server (the Java EE reference implementation), but it should work on any Servlet 3.X container.
While the application works as-is, there is another aspect to consider that I will (hopefully) cover later. Some components will reload their data when a page is refreshed, for instance a Table that only shows a subset of its rows. In this case, the refresh call will force tables to make subsequent calls back to the server, extending the session. I'll add tables and their request handling to this sample application in a separate blog.