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.
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:
- Create the SystemEventListener class and implement the logic for writing out the script documented above.
public class LiferayListener implements SystemEventListener {...
- 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.