One of my sessions for BLUG, The Eureka Moment: The JSF Knowledge You Need To Understand XPages, has led me to investigate XPages optimisation and partial refresh processing to an extent I haven’t in the past. Much of the evidence gained has been illuminating for me too and has given me an understanding which will make me and my team think more when developing our XPages applications in the future. The JSF lifecycle and its quirks, seems to be a topic more developers have been delving into recently or hitting the impacts of:
- Tony McGuckin has posted an XSnippet for tracking the XPages and JSF lifecycle.
- Ulrich Krause has posted a topic on the XPages Forum about dataContext recalculating when outside of the refreshId area
- Andrew Pollack posted a question on Stack Overflow because he had suffered major frustration when trying to edit a row in a repeat control, because validation on a new document was triggering.
As part of my preparation for BLUG I investigated all the partial refresh options. One that I have never used but gave me a eureka moment, was Partial Execution Mode. It is the option that answered both questions, as I’ve been able to prove, thanks to both developers posting their code. (And, by the way, this is one of the wonderful benefits of XPages, that developers can post their code.)
So What Happens During a Partial Refresh?
Well, I can’t cover everything here. That’s a big chunk of my session at BLUG. And I’ll work from Ulrich’s code. There’s a screenshot below, but if you follow the link to his post above, you can download it.
First of all, the whole XPage is posted back to the browser. This is the default action and will occur for most of you for most of your XPages, unless specifically coded differently. That’s outside the scope of this post and won’t affect the later processing.
Secondly, the server processing occurs. I’ll come back to that.
Finally, the area in the refreshId, highlighted in the screenshot, is passed back to the browser.
RefreshId: WHICH Refresh?
We’ve mentioned refreshId here. The key thing to remember here is that the refreshId defines the area that will be refreshed back to the browser. The refreshId has absolutely no effect on the server processing, and that is very important to remember. Regardless of what is put in refreshId, the whole XPage is recalculated by the server processing, during the relevant phases of the JSF lifecycle. This is evidenced when you use a phaseListener to show what is updated during each phase (see Tony’s XSnippet for how to do that).
The value property of the dataTable is calculated during the Apply Request Values phase as well as the Render Response phase (see below).
Add a Computed Field with a value calculated in SSJS and you will see it is calculated during the same two phases. Add a rendered property calculated using SSJS to the Computed Field and you will see that the rendered property is recalculated during the Apply Request Values, Process Validation, Update Model Values and Render Response phases.
And by default, every control in the whole XPage is recalculated. The fact that this hasn’t been so widely noticed is a credit to the performance of XPages.
ExecMode and ExecId To The Rescue
On every event there is a little checkbox which a lot of developers – myself included – have always left as one of those pieces of advanced XPages functionality to look into at one point in the future. I reached that point recently.
The setting is Set partial execution mode. In the source pane this converts to execMode=”partial” set on the eventHandler. This changes what is processed in the server side processing. Instead of processing the whole XPage, it processes a specific component.
Once execMode is set to partial and execId is set, the full JSF lifecycle only processes those components within the ID defined for execId. This will significantly cut down the number of calls to the server. The value property of Computed Field controls will not be calculated at all during the JSF lifecycle. Currently the rendered property of the Computed Field and the value property of the Data Table will still get calculated during the Render Response phase. The screenshot below shows the value property of the Data Table. But the properties are not recalculated during any other phase.
It also means that if, like Andrew Pollack, you have a repeat control where you want to toggle edit mode and validation for one row while not triggering validation for a second datasource on the XPage, setting execMode and execId will do that for you.
However, bear in mind the impact of execMode and execId. Because the component tree is only updated for the components within the execId, that means other values entered by the user do not get applied during the Apply Request Values phase. That means all values entered by the user outside of the execId area revert back to what they were the last time a refresh occurred.
So it has real benefits for performance, for logical processing, but the impacts must be understood. Hopefully this article has given you enough information to understand the impacts and, if not, enough information to work them out for yourself. It’s a piece of functionality I will certainly be using more often in the future.