Archive | JSON RPC RSS for this section

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.

Advertisements

Handling Errors in an XPages RPC Method

The Remote Service (aka xe:jsonRPCService) is an extremely useful control in XPages because it examples client- and server-side code interaction, runs asynchronously, performs well, and is easy to use. But if you don’t handle errors well, it can fail quietly and the user may never know. In this post, I’ll show how to handle client- and server-side JavaScript errors with an RPC method.

Remote Procecure Example

As a starting point, let’s look at an example of a simple RPC method that returns the date and time and displays it for the user.

RPC Control

Here’s the XPages component source:

<xe:jsonRpcService id="jsonRpcService1" serviceName="myRPCService">
  <xe:this.methods>
    <xe:remoteMethod name="myMethod" script="return myLibraryFunction();">
    </xe:remoteMethod>
  </xe:this.methods>
</xe:jsonRpcService>

The service name is myRPCService. The method, myMethod takes no parameters and just calls an SSJS library function named myLibraryFunction().

SSJS Library Function

Here’s the SSJS function that it calls:

function myLibraryFunction() {
  var d = new Date();
  return d.toLocaleString();
}
Client-Side JavaScript

Here’s the code that calls the RPC method:

myRPCService.myMethod().addCallback(function (response) {
  alert('response: ' + response);
})

It calls the method in the RPC service and attaches a callback function to wait for the response. It then displays the response to the user in an alert.

RPC Error Handling - A

Handling Client-Side Errors

This works well and RPC functionality is awesome, but you have to be careful about how you handle errors.

Take for example, this problematic update. This code ignores the response, but tries to display an invalid value (an undeclared variable) in an alert.

myRPCService.myMethod().addCallback(function (response) {
  console.log('before');
  alert ('Invalid variable: ' + myUndeclaredVariable);
  console.log('after');
})

When you run the code, it appears that nothing happens. The console shows the ‘before’ statement, but it then fails quietly.

Putting a try-catch block around it like this doesn’t help at all.

try {
  myRPCService.myMethod().addCallback(function (response) {
    console.log('before');
    alert ('Invalid variable: ' + myUndeclaredVariable);
    console.log('after');
  })
} catch (e) {
	alert('Error: ' + e.toString());
}

This may seem a bit confusing, but it actually makes sense. The callback effectively runs in its own scope, so the error handling needs to be within the callback in order to fire when dealing with an RPC call.

This code does the trick:

myRPCService.myMethod().addCallback(function (response) {
  try {
    console.log('before');
    alert ('Invalid variable: ' + myUndeclaredVariable);
    console.log('after');
  } catch (e) {
    alert('Error: ' + e.toString());
  }
})

RPC Error Handling - B

Handling Server-Side Errors

If there’s an unhandled exception on the server-side code that runs (such as an error or forgetting to return a response), it also fails quietly, although it will show a few errors in the browser console.

RPC Error Handling - C

If you expand the POST, you’ll see that it returns a stack trace for an RPC error.

In this case, error handling in the client-side callback function doesn’t help at all, so it’s important to handle the error in the server-side code and return something that the callback can deal with.

function myLibraryFunction() {
  try {
    print (myUndeclaredVariable);
    var d = new Date();
    return d.toLocaleString();	
  } catch (e) {
    return 'Error: ' + e.toString();
  }
}

RPC Error Handling - D

Now, I’m returning a more informative message to the user about what went wrong.

I generally like to set up my server-side methods to return an object to the callback function, because that way I can add as many properties as I want in order to return all of the information that I need. I generally include a property for a boolean value for whether the method was successful and another value that contains a success or error message. In the callback, those values can be checked and appropriate action can be taken accordingly.

MWLUG Slides – AD114 Take Your XPages Development to the Next Level

In this session at MWLUG 2015, Paul Calhoun and I dug into a number of features already available in XPages, but not as widely used.

We only had time to cover half of the sections, but the full set of slides is available here

Topics include:

  1. Application Responsiveness (primarily JSON RPC)
  2. SSJS Tips
  3. Modifying Component output
  4. Java Tips
  5. Custom Controls (including dynamic field binding to make reusable fields)
  6. Resources for learning more
  7. Debugging Tips
  8. Event handlers
  9. Dojo

Article Published in The VIEW: Improve Application Performance with JSON-RPC

An article that I wrote on improving XPages application performance using JSON RPC has been published in The VIEW journal (subscription required).

One of the best-kept secrets of XPages is JSON-RPC control. It is the ideal solution for application developers who want:

  • Their XPages applications to be more efficient and run faster
  • To easily implement client-side and server-side JavaScript interaction

Abstract

If you want your XPages applications to perform more efficiently, or if you’ve ever struggled with executing server-side JavaScript from client-side JavaScript (or taken it a step further and plotted hacktastic workarounds for passing information back and forth), then you need to get to know JSON-RPC. Compared to workarounds that involve partial refreshes, JSON-RPC is a much cleaner method of client and server code interaction and is much more efficient because there is no form submission. JSON-RPC is also asynchronous, so it’s faster and appears more responsive because it doesn’t block user interaction. In this article, get an introduction to JSON-RPC and learn how to reap the benefits in your XPages applications.