Blog

Understanding Partial Execution: Part Three – JSF Lifecycle

  |   Blog   |   5 Comments

In the previous two parts of this series I’ve focussed on partial refresh and partial execution. But in order to fully appreciate why partial execution is important, you need to understand the JSF lifecycle. Part two focussed on what gets processed from the XPage, it’s important to understand how it gets processed. Remember that if execMode=”partial”, then the following phases only run for the execId. Outside of that area, nothing gets written back to the server and nothing gets recalculated.

Phase 1: Restore View

Previously I mentioned there is a server-side map of the XPage and it’s current state – the component tree. The first phase is to restore the component tree, so any changes from the latest submission from the browser can be applied.

Phase 2: Apply Request Values

Now any editable content added via the browser is extracted from the submission from the browser and stored against each component. If execMode is “full” then everything entered in the browser is passed to submittedValue. If execMode is “partial” only the content within the execId is passed to submittedValue. Everything else is discarded and will not be available for your SSJS.

Remember also that the browser content comprises only strings. At this point, the content against each component is still also stored as strings, calling this.getSubmittedValue(string). In submittedValue, strings are string, numbers are strings, dates are strings.

If “do not validate or update values” is selected (immediate=”false”), then your Server-Side JavaScript runs at this point. If you want to retrieve values from the components in that SSJS, you need to use getSubmittedValue(). After the SSJS has run the JSF lifecycle is skipped through to phase 6, Render Response. The values are not stored any further into the component tree.

Phase 3: Process Validation

If immediate=”false” the submittedValue for each control is now validated against any validators, unless “process data without validation” is selected. But converters are also applied, and you cannot skip converters. That means that if you have a number converter, even if you process data without validation, if a non-numerical value is entered, the XPage will still throw an error. If any errors – from converters or validators – are thrown, the JSF lifecycle is skipped through to phase 6, Render Response. That means that your SSJS will not run.

As well as basic validators, you can add custom validators – in SSJS or Java – and they will run at this point. And this is why those validators need to use getSubmittedValue() to validate the values, because the value is still in submittedValue and has not yet been moved to value.

Phase 4: Update Model Values

Now the submitted values have been tested with converters and, if not overridden, validators. They are values that can be converted to the underlying datasource’s data type. So now for each component setValue(this.getSubmittedValue()) is called, the contents are moved to value and sibmittedValue is set to null. This is why, in the normal JSF lifecycle, you call getValue() instead of getSubmittedValue().

Phase 5: Invoke Application

Unless immediate is set to “true”, it is at this point that SSJS (your application logic) is run. Remember again that if execMode is “partial”, the only content just entered in the browser that you can use, is what is within the execId.

Phase 6: Render Response

Now, for partial refreshes, the refreshId is used. That content is passed back to the browser.

So Why Is ExecId Important

Any computed or rendered properties will also get recalculated during various phases of the JSF lifecycle. This is why execMode=”partial” and execId is important. Because those properties don’t just get recalculated once. They get recalculated a number of times. That’s because they may affect the processing. Look at the analysis below, using a PhaseListener, and measured on 8.5.3 (the stats may be better in Social Edition). I’m using 1 computed field with the value property computed using SSJS and two edit boxes with the rendered property computed. For the final two tests, execMode is set to “partial” and the execId comprises just one edit box. For two tests, the rendered property is computed in a dataContext and the edit boxes just reference that dataContext. The differences in the amount of processing is significant.

JSF Lifecycle Results

This is why using “${javascript:…}” can offer significant benefits and why using “loaded” properties instead of “rendered” properties is important. Combine all of these, and you can significantly improve performance of a large XPage.

One final comment is that this investigation has given me a huge appreciation for the performance of XPages. But if you have performance issues, hopefully you have an appreciation of some steps that can be taken to improve the performance, but more importantly, enough of an understanding to refine it in a way to avoid unexpected results.

AUTHOR - Paul Withers

Paul Withers has been an IBM Champion since 2011, has been an OpenNTF Board Member since 2013, has worked with XPages since 2009, co-authored XPages Extension Library and was technical editor for Mastering XPages 2nd Edition. He is one of the developers on OpenNTF Domino API as well as contributor to a variety of other OpenNTF projects.

5 Comments
  • Julian Buss | Jan 24, 2013 at 8:20 pm

    Excellent articles, Paul. I learned one thing or two I didn’t knew yet 🙂

    • paulwithers | Jan 27, 2013 at 2:43 pm

      Thanks, but you can go in further to improve performance even more. It’s a credit to what Phil Riand and everyone else has coded XPages, so that it works as well as it does without needing to understand all this.

  • @michaelgsmith | Feb 17, 2013 at 4:14 pm

    I’ve started implementing partial execution mode on a large Xpage that slowed down significantly when a large data source was added. It’s made a big difference in some cases. However, I’m having some issues with the following scenario:

    – Button1 on panel1 updates some view scope variables and refreshes panel2
    – Panel2 reads the view scope values but now they are not there because partial execution mode implemented on button1 has an execId of panel2

    Based on the description in “Apply Request Values” it looks like this is expected behavior?

    This is a huge problem since this type of scenario exists in several places on my XPage. I have a workaround but it’s a bit of a hack.

    • paulwithers | Feb 17, 2013 at 4:55 pm

      Yes, it sounds like that’s standard behaviour. My usual rule of thumb would be execute over an ID that incorporates any submitted area and any refresh area.

Post A Comment