The order of events in XPages

After reading another question on the XPages forum about which (serverside) events are triggered if you use the browsers “back” button on on XPage, I decided to run some tests.

First thing I did was to set up a simple test XPage (page1.xsp):

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

<xp:this.beforePageLoad>
<![CDATA[#{javascript:print("beforePageLoad")}]]>
</xp:this.beforePageLoad>
<xp:this.afterPageLoad>
<![CDATA[#{javascript:print("afterPageLoad")}]]>
</xp:this.afterPageLoad>
<xp:this.afterRestoreView>
<![CDATA[#{javascript:print("afterRestoreView")}]]>
</xp:this.afterRestoreView>
<xp:this.beforeRenderResponse>
<![CDATA[#{javascript:print("beforeRenderResponse")}]]>
</xp:this.beforeRenderResponse>
<xp:this.afterRenderResponse>
<![CDATA[#{javascript:print("afterRenderResponse")}]]>
</xp:this.afterRenderResponse>

<xp:link escape="true" text="Go to page 2" id="link1">
<xp:this.value><![CDATA[#{javascript:"page2.xsp"}]]></xp:this.value>
</xp:link>

</xp:view>

The order of events triggered when opening this XPage is as expected:

  • beforePageLoad
  • afterPageLoad
  • beforeRenderResponse
  • afterRenderResponse

 

Note that the afterRestoreView event isn’t executed: that event gets only executed after a (partial) refresh of the page.

If I open another XPage (page2.xsp) from my sample page using the link on page 1 and then click the browser’s back button (or a clientside link calling history.go(-1) ), no events are executed at all. That’s because the page is served from the browser cache, despite the fact that a Expires header is added by default with a value of -1 !

 

Control caching using a Cache-Control header

 

The Expires header is one way to control caching, the Cache-Control is another, so I checked what would happen if I added that one. I added this to the beforePageLoad event of page1:

var exCon = facesContext.getExternalContext();
var response=exCon.getResponse();
response.setHeader("Cache-Control", "no-cache");

That didn’t change anything, so I tried another:

response.setHeader("Cache-Control", "no-store");

(read this for the difference between no-cache and no-store)

That changed something: using the back button now causes page1 to execute the same list of events as mentioned before. So it seems that the no-store header actually causes the XPage not to be cached at all and opening an XPage using the back button had the same effect as initial opening it.

onClientLoad

With that in mind I tried something else: I added a serverside onClientLoad event to page 1:

<xp:eventHandler event="onClientLoad" submit="true" 
  refreshMode="norefresh" execMode="partial">
<xp:this.action><![CDATA[#{javascript:print("ocl");}]]></xp:this.action>
</xp:eventHandler>

As you can already see from the syntax, this event is different from the other XPage events. If you now open page 1, the XPage instantly performs a POST request to handle the onClientLoad event. That in turn causes the beforeRenderRespons, afterRenderResponse and afterRestoreView events to be executed.

If I know open page 2 and click the browser’s back button those events are also executed. So by adding an onClientLoad event you can force events to be executed (with the downside of an extra POST request on every access of the page).