When XPages works, it’s great. When it doesn’t work, it’s a pain. Partial refreshes suddenly stop working, user data is thrown away, and forms become unsubmittable.
The root problem is that JSF holds a complex tree of objects on the server, representing the state of all the components on the web page — along with a Domino document for your data, and all the scope variables. Each HTTP request to the back end is accompanied by a
$$viewid value fetched from a hidden field on the Web form. The server uses this to fetch the JSF object tree, apply the changes, run the appropriate code on all the components, and then pass back the results.
The good side of this is that you can attach code to components which performs lookups, manipulates document data, and so on — without having to care about the distinction between client web browser and Domino server.
The bad side is that if the hidden
$$viewid gets lost, or the server drops the component tree for some reason, the user ends up with a web page that doesn’t work, even though it worked a minute ago and apparently nothing has changed.
One reason why the server drops component trees is to save memory. JSF doesn’t just store the tree once — it resaves it for every “page” displayed to the user, keeping a history of the last N states of the tree. This chews up memory, and when the server runs out of memory, things go wrong.
Having spent a week or so chasing down dying JSF sessions and finally achieving reliability, I thought I’d put together a list of things to check.
Java object memory leaks
The first thing to do is to check that none of the Java code called by your XPages leaks memory. Recall that any Domino Java class is a wrapper around some native C code, and you need to call
recycle() on every single Domino object when you’re done with it. Yes, even Session objects.
Domino 9.0.3 is supposed to introduce JVM 8, at which point it should be possible to use an
AutoClose wrapper to handle this. There’s also the OpenNTF Domino API, but I don’t use that because it’s incompatible with CORBA/DIIOP, and I have a lot of Java code which runs outside the server and communicates via DIIOP.
Under Application Configuration > Xsp Properties > Persistence you’ll find a set of options controlling how JSF handles the component tree.
For the first drop-down (Server page persistence) I favor “Keep only the current page in memory”. This one is rather misleadingly worded. You might think that it means “Keep only the current page, throw away all the others”, but it actually means “Keep the current page in RAM, and put the historical data on disk” — so you don’t actually lose any functionality.
The second drop-down selects page persistence mode. For this, I seem to get the best results when I choose “Only changes since the tree was constructed”. In this mode, JSF builds a complete page tree once when you load the form, but partial refreshes and other updates only result in the changed data being stored in the server session.
(This information is hidden away in the XPages Portable Command Guide.)
Unnecessary data passing
Once you’ve told XPages to only store changes rather than the entire tree each time, the next thing to do is limit the possible scope of changes as much as possible. That means going through your forms and making sure you use partial refresh and partial execution as much as possible.
I’m not sure whether the runtime is smart enough to know that recomputing a value to the same value as before means that it doesn’t need to be stored. Perhaps it is, but it’s a good idea for performance to limit refresh scope anyway.
For the server to keep a session active, it needs to know that the client is still there. The XPages Extension Library has a Keep Session Alive control, but it doesn’t seem to work very well. Instead, I use a period partial refresh.
Finally, it goes without saying that your Domino server should have plenty of RAM and disk space. However, don’t be fooled into thinking that just because the server has lots of resources, it can’t be throwing away sessions for resource reasons — even a 64 bit server with 40GiB of free RAM will drop sessions, in my experience.