Efficiently Keeping an XPages Session Alive with JSON RPC

In my last post, I talked about the difference between two reasons that a user may be prompted to login again while using an XPages application: idle session timeouts and LTPA token expiration. There are a variety of ways to programmatically prevent an browser session from timing out due to inactivity. In this post, I’ll show how to do it with JSON-RPC and why I prefer it to the standard methods.

Keeping the Session Alive

The Keep Session Alive control (xe:keepSessionAlive) in the extension library was designed to make it easy to prevent idle session timeouts; all you have to do is drop the control onto a page and optionally set the refresh period and it will send requests to keep the session alive.

In earlier versions of Notes/Domino, this would not be available without the extension library, which was a limiting factor in many situations. It’s built into version 9+, so it’s more readily available.

Other solutions popped up for those without the extension library (and to work around an earlier bug in the control, including Mark Roden’s XSnippet. In this solution, a timer is set to periodically trigger a partial refresh of an empty div in order to send a request to the server and keep the session alive.

This works well and is easy to add to any application.

However, while it can be set to run very infrequently, the partial refresh is more overhead than necessary. It only refreshes a single empty DIV tag, but it’s still posting the entire form and causing the entire component tree to go through most of the life JSF lifecycle. If the user happens to be viewing the page, the responsiveness may lag due to the synchronous processing and refresh.

Keep Alive 2A - Keep Session Alive XSP partial refresh

(In contrast, the Keep Session Alive control appears to be efficient, sending a GET request and getting a minimal response.)

Keep Alive 2B - Keep Session Alive control

RPC Efficiency

My first thought when looking for a more efficient solution was, at minimum, to use the code to trigger an even that for which I could also enable partial execution (explained really well here by Paul Withers) to limit the scope of the processing to make it much more efficient.

However, in thinking through it further, I realized that it would be even more efficient to use JSON RPC, because the amount of information sent is minimal, the response is minimal, and the request is asynchronous, so it doesn’t have any of the aforementioned issues. (If you’re not familiar with JSON RPC — take a look at the first section of this presentation for more information.)

Without further adieu, here is a solution using JSON RPC.

<xe:jsonRpcService id="jsonRpcService1" serviceName="rpcUserSession">
  <xe:this.methods>
    <xe:remoteMethod name="keepAlive">
      <xe:this.script><![CDATA[return '';]]></xe:this.script>
    </xe:remoteMethod>
  </xe:this.methods>
</xe:jsonRpcService>
	
<xp:eventHandler event="onClientLoad" submit="false">
  <xp:this.script><![CDATA[ setInterval(function(){ console.log('keeping session alive (rpc): ' + new Date()); rpcUserSession.keepAlive(); }, 1500000) ]]></xp:this.script>
</xp:eventHandler>

The first 8 lines simply define an rpc service that has a single method that just returns an empty string.

The last 8 lines are an onClientLoad event handler that set a timer to write a message to the browser console and call the RPC method every 25 minutes.

The request sent to the server is minimal…

Keep Session Alive 2F - RPC Post

… as is the response.

Keep Session Alive 2F - RPC Response

No page processing occurs and the request is asynchronous, so it cannot affect the user.

This can be added to it’s own custom control and then added to your application’s page layout control so it’s available throughout. All you have to do is set the refresh duration, which should be slightly less than the idle session timeout.

Timeout Handling

In addition to being more efficient, this method also has the benefit of failing much more gracefully and also providing the ability to handle the timeout.

In my testing the Keep Session Alive control doesn’t show any error to the user or to the browser console.

The partial refresh method first shows this message…

Keep Session Alive 2C - Partial Refresh Failure

…and then pops up a second error message, saying that there’s no element to submit, along with the client-side ID of the <div> that’s the target of the partial refresh.

Keep Session Alive 2C2- Partial Refresh Failure 2 - No Element to Submit

This is an ugly way to fail.

One of the benefits of the RPC method is that it fails more gracefully AND you can trap the error and handle it however you’d like.

Here’s the error message that is displayed in the browser console when the session ends due to the machine going to sleep:

Keep Session Alive 2D - RPC Post Failure Due to Machine Going to Sleep

A different message is returned when it times out due to the expiration of the LTPA token:

Keep Session Alive 2D2 - RPC Post Failure When Timed Out

The user never gets a message. They would just be prompted to login the next time they tried to run any action on the page that required server interaction.

However, as I described in a previous post, you can handle errors within an RPC call. You could use this to either display a nicer message to the user or redirect to a login page, either of which allows you to handle it much more gracefully.

One response to “Efficiently Keeping an XPages Session Alive with JSON RPC”

  1. YusranCorp says :

    Thank you, Brad!
    If you want to hide the domain being used in the test, please note that it’s exposed in the image before the last.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: