Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep a session alive for an indefinite amount of time

Is there a way to keep a page's session active without resorting to sending the state to the client? I'm not able to set the STATE_SAVING_METHOD to client and I'd prefer to not use the a4j:keepalive.

I've tried using a simple hidden iframe that submits to the Bean in question but it invalidates the main page.

I am using JSF 1.2 and myfaces.

This is to get around a ViewExpiredException on a page that does not require the user to log in. The majority of the existing site requires the user to log in.

like image 250
OddProblems Avatar asked Dec 03 '22 00:12

OddProblems


2 Answers

Implement an ajax poll as a "heartbeat" to keep the session alive. At its simplest you can achieve this as follows with help of a little jQuery to avoid boilerplate code of 100 lines to get it to work across all different browsers the world is aware of:

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
    $(document).ready(function() {
        setInterval(function() {
            $.get("${pageContext.request.contextPath}/poll");
        }, ${(pageContext.session.maxInactiveInterval - 10) * 1000});
    });
</script>

The ${pageContext.session.maxInactiveInterval} prints the remaining seconds the session has yet to live according to the server side configuration (which is by the way controllable by <session-timeout> in web.xml) and is been deducted with 10 seconds, just to be on time before it automatically expires, and converted to milliseconds so that it suits what setInterval() expects.

The $.get() sends an ajax GET request on the given URL. For the above example, you need to map a servlet on the URL pattern of /poll and does basically the following in the doGet() method:

request.getSession(); // Keep session alive.

That should be it.

like image 118
BalusC Avatar answered Dec 19 '22 14:12

BalusC


BalusC's answer helped me to meet this requirement in my app, but since I'm using PrimeFaces, I wanted to share how BalusC's answer inspired the code i'm using to do this.

xhtml page

<p:poll listener="#{pf_usersController.keepUserSessionAlive()}"
        interval="#{session.maxInactiveInterval - 10}" />

bean

public void keepUserSessionAlive() {
    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    request.getSession();
}

as always, thank you, BalusC!

EDIT: An enduser put this to the test this morning, and it is working great! my app usually forces session timeout 15 minutes after full page refresh (redirect to sessionExpired.xhtml via meta refresh based on session.maxInactiveInterval and session timeout value in web.xml); if user is on one page doing a bunch of AJAX requests, session will timeout, since AJAX != full page refresh, but this code allowed enduser to 'keep session alive' while enduser was on payroll page in the app, and session stayed alive for 1 to 2 hours! :)

like image 31
Howard Avatar answered Dec 19 '22 15:12

Howard