Timeout via PrimeFaces p:idleMonitor

leostiw picture leostiw · Mar 20, 2013 · Viewed 12.6k times · Source

I am trying to handle the session timeout via idlemonitor, a primefaces component.

I am doing this because i need to let the user know that due to inactivity the session has expired. I need to display this message through a dialog, after he closes the dialog he should be redirected to the loginpage. He should not be able to click "back" and browse on the application just as nothing happend; if he clicks "back" he should be redirected to a sessionexpired.xhtml page.

I put the idleMonitor in my loggedintemplate.xhtml, so it works only if you are logged in, no matter on what page, beacause all my pages, after you logged in, derives from the loggedintemplate.xhtml.

This is how the code in my loggedintemplate.xhtml looks like:

<p:idleMonitor timeout="6000" onidle="idleDialog.show()" />

<p:dialog header="Timeout" resizable="false" closable="false" 
          widgetVar="idleDialog" modal="true">
    <p:panel styleClass="noborderpanel">
        <p:panelGrid columns="1" styleClass="adressegrid">
            <p:outputLabel value="Session has expired due to inactivity" />
                    <p:commandButton action="#{loginController.timeout()}"
                        value="Ok" />
        </p:panelGrid>
    </p:panel>
</p:dialog>

So the functionality of this code basically checks if the user was inactive for 6 seconds, if he was inactive, a un-closeable dialog pops up and tells him that the session has expired.

The method loginController.timeout() should log the user out, invalidate the session etc.

My problem is that I don't know how to invalidate the session, how to log out the user etc. If I use FacesContext.getCurrentInstance().getExternalContext() .invalidateSession(); it does invalidate the session, but I need more. For example, if the user is inactive for more than 30 min, the default JavaEE timeout time, i get a nullPointerException.

I want to handle the timeout "manually", is there a way to disable the default JavaEE timeout?

What is the best way to handle the timeout manually, not like this:

<session-config>
    <session-timeout>20</session-timeout>
</session-config>   
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/expired.xhtml</location>
</error-page>

Answer

leostiw picture leostiw · Mar 21, 2013

I've found a solution that works pretty nice, and i don't have to deal with the NPE.

Following scenario:

If the user is idle for more than 6 sec, the session is invalidated through ajax, no user interaction required. That means, even if the user is idle for more than 20 minutes, the session is already invalid and I don't have to deal with the NPE.

After 6 seconds a dialog(through javascript alert) is generated and lets the user know that he was inactive for a certain amount of time and the session has expired. After the dialog is closed, the user is redirected to the login page.

By the way, i used 6 seconds just for testing purposes. My default settings are:

  • idlemonitor: 30 min
  • web.xml: 40 min (just to ensure that the session is always invalidated manually and the users gets to see the dialog with the session expired information)

This solution matches exactly to my requirements.

Code for idlemonitor:

<!-- language: lang-xml -->

<p:idleMonitor timeout="1800000" >
    <p:ajax event="idle" listener="#{loginController.timeout()}" oncomplete="alert('Session expired etc.')"/>
</p:idleMonitor>

Code for loginController.timeout():

public void timeout() throws IOException {
    FacesContext.getCurrentInstance().getExternalContext()
            .invalidateSession();
    FacesContext.getCurrentInstance().getExternalContext()
            .redirect("...loginpage.xhtml");

}