Liferay Client Session Tracker

Table of Contents

Liferay Client Session Tracker

Liferay provides a feature that tracks the session activity on the client and provides the means, at a configurable interval, to display a warning that the session is about to expire. This client-side tracker relies on detecting when a request is sent to the server and adjusts its own internal timer appropriately.

Ajax Requests

One of the difficulties with the client-side session tracker is dealing with Ajax requests. Ajax requests from 3rd-party libraries are not typically detected by the tracker which can lead to the tracker issuing a warning and displaying the warning/expiration banner even though the user has been actively interacting with one or more portlets on the page. In order to help with this, Liferay provides a client-side API that libraries like ICEfaces can call when making Ajax requests to help keep the tracker notified of user activity.

However, in Liferay versions prior to 6.1.0 CE RC1 and 6.0.12 EE, the tracker and its API has bugs that prevent it from working properly in certain use cases. The following JIRAs contain additional technical details about the various fixes and changes to the APIs documented here.

Liferay.Session Client API

The follow sections detail the Liferay.Session APIs, both before and after the main work was done to fix the various issues.

Original Liferay APIs

In versions of Liferay before the fix in LPS-17624 (i.e. before 6.1.0 CE RC1 and 6.0.12 EE), the Liferay.Session API provides two possible ways of notifying the client-side session tracker that something has occurred and that the timer should be reset.

The first is the extend() function. This is the most reliable mechanism but sends a separate request to the server to ensure the session is also touched on the server-side. This request is in addition to the actual Ajax request that is being made as part of the normal user-interaction:

Liferay.Session.extend();

The other is the setCookie() function which does not send a separate request to the server.

It is not recommended to use this API. It wasn't intended to be used to notify the client-side session tracker and its behaviour is unreliable under various conditions. The API was eventually removed at part of the work for LPS-17624.
Liferay.Session.setCookie();
New Liferay APIs

In versions of Liferay after the fixes for LPS-17624 (i.e. starting from 6.1.0 CE RC1 and 6.0.12 EE), the Liferay.Session API provides two possible ways of notifying the client-side session tracker that something has occurred and that the timer should be reset:

Just like in previous versions of Liferay, the extend() function is still supported. While it now works more reliably, the behaviour is much the same as in previous versions of Liferay in that it sends a separate request to the server. It's best to use this API when you are doing primarily client-side behaviours but still want to notify the server that the session should be kept active. It's also a good choice if you need to support a codebase across multiple versions of Liferay.

Liferay.Session.extend();

The recommended approach is to use the Liferay.Session.set() function. By accepting various parameters, this function allows the developer more control over the state and behaviour of Liferay's client-side warning system. In addition, this function does not make an additional call to the server so it's the ideal choice to use for a framework like ICEfaces where an Ajax request is already being made to the server. However, it's only available in relatively recent versions of Liferay.

Liferay.Session.set('sessionState', 'active');

ICEfaces Client API

To effectively use the Liferay API, we need to hook it in to the appropriate spot in ICEfaces so that with each Ajax request submitted, the client-side session tracker is notified. This depends on which version of ICEfaces is being used.

ICEfaces 1.x API

In ICEfaces 1.x, the client API for registering a callback you want called before a request is sent is:

ice.onSubmitSend(callBackFunction);

This function is deprecated but still supported in current releases of ICEfaces for backwards compatibility.

ICEfaces 2.x+ API

In ICEfaces 2.x+, the client API for registering a callback you want called before a request is sent is this:

ice.onBeforeSubmit(callBackFunction);

Register a Callback

In order to notify the client-side tracker with each Ajax request, you need to do a couple of things:

  • Create a script that registers a callback so that with each Ajax request sent by ICEfaces Liferay's client-side tracker is notified.
  • Include the script with each ICEfaces portlet.
The Registration Script

The following is a fully documented snippet of JavaScript that outlines an example of a script you can use. There are a couple of choices to make depending on your environment - the version of Liferay you are using and the version of ICEfaces.

    // Check to see if we've registered this function yet.
    if(!extendLiferayClientTimer){ 
    
        // Define the function to be called with each Ajax request to extend Liferay's 
        // client-side session tracker.
        var extendLiferayClientTimer = function() { 
            
            // Check to ensure that the Liferay.Session API is available.
            if(Liferay.Session){
                
                // Call *only 1* of the following functions depending on the version of
                // Liferay you are running:
                 
                // The extend() function works in all versions of Liferay but does make an
                // extra call (in addition to the Ajax request) to the server to extend the
                // session.
                Liferay.Session.extend();
                
                // This is the recommended function to call as it doesn't make an additional
                // request to the server but it is only available in versions of Liferay 
                // since LPS-17624 was fixed.  
                // Liferay.Session.set('sessionState', 'active')
                
                // This is the only option available if you are running in older versions
                // of Liferay and you don't want to make an extra request to the server.
                // However, it can be unreliable and is not generally recommended by 
                // Liferay or ICEsoft. 
                // Liferay.Session.setCookie(); 
            } 
        }; 
      
        // Check to ensure that Liferay API is available.
        if (Liferay) {
        
            // Call *only 1* of the following functions depending on the version of ICEfaces 
            // you are running:
                 
            // For ICEfaces 1.x, the register the callback function for all Ajax requests.
            // It's currently deprecated but supported in ICEfaces 2.x+ for backwards 
            // compatibility.
            ice.onSubmitSend(extendLiferayClientTimer); 
            
            // For ICEfaces 2.x+, the register the callback function for all Ajax requests.
            // ice.onBeforeSubmit(extendLiferayClientTimer); 
        } 
    } 

Including the Script in ICEfaces 2.x+

There are different ways to do this depending on which version of ICEfaces and JSF you are using. With ICEfaces 2.x+ you can take advantage of some of the new features and integration points of JSF 2.0. One way to do this is to create a SystemEventListener that automatically adds the script to the markup of the portlet. The main steps to do this are:

  1. Create the SystemEventListener class and implement the logic for writing out the script documented above.
public class LiferayListener implements SystemEventListener {...
  1. Register the listener in the faces-config.xml for the appropriate event.
<faces-config>

    ...

    <application>
        <system-event-listener>
            <system-event-listener-class>org.icefaces.impl.util.LiferayListener</system-event-listener-class>
            <system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class>
        </system-event-listener>
    </application>

</faces-config>

As an example of how to do this, download the attached example project that shows one way this can be done:

Including the Script in ICEfaces 1.x

Because ICEfaces 1.x uses JSF 1.2, SystemEventListener is not available so the same technique cannot be used. One alternative would be to write out the script contents from a backing using an outputText component:

<h:outputText value="#{myPortletScriptBean.extendSessionScript}" escape="false"/>

However, there are other ways to get scripts into the content of a Liferay portlet. Use the one that suits your needs best.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

© Copyright 2021 ICEsoft Technologies Canada Corp.