I've mentioned before in my presentations on Themes in XPages that deferring as much component property evaluation to Themes as possible actually makes XPage execution more efficient. But I've recently had a reason to investigate more thoroughly the reason for that result, so I wanted to share my findings. I've been able to identify two completely separate reasons for this increased efficiency (although there certainly could be more):
Themes are not evaluated until the "render response" phase, which is the last of six phases in the JSF lifecycle. As a result, component properties that are only specified in a Theme are ignored during the first five. There's obviously a lot going on in those other phases, so the less properties of each component that are evaluated during those phases, the sooner the final phase can begin.
This does, of course, have several implications:
Any properties that are overridden (or appended) via a Theme do not benefit from this particular performance gain. If the property already has some local value or value binding, that must still be processed during the earlier phases; the Theme evaluation simply occurs in addition to the earlier processing.
Properties should only be moved to a Theme if they are inherently read-only (styleClass, value of labels, etc.). If they impact back end data, event processing, or even just the structure of a page (e.g. the value attribute of a repeat), they cannot be moved to a Theme, because earlier phases need the attribute values to perform tasks not explicitly related to sending HTML markup to a browser.
When rendering the value of a component attribute, the renderer asks whether the value has been set via a Theme before checking the component itself.
Every component in an XPage is an instance of a Java class that extends UIComponent; hence, one method all components share is getAttributes(). This method returns a specific implementation of the Java Map interface. All scope variables are Maps, so if you've done any scope caching, by now you're used to calling get() and put() on Maps. What is significant about the attributes Map is that it is aware of its container. With scope variables, if you call get() and pass it a key that doesn't exist, it just returns null. A component's attributes Map, however, is aware of the component with which it is associated. As a result, if you pass "width", for example, to get(), and that key doesn't exist, it uses Java reflection to determine that it should call the component's getWidth() method. As I've mentioned elsewhere, this type of method asks if the component has a non-null value for the property to return; if not, it then looks for a value binding associated with that property and, if one exists, returns the result of evaluating that binding's expression in real time. Ergo, even more efficient than storing a local value for a property (as compared to assigning a value binding) is to store the value in the component's attributes Map. This is the first place the renderer will look - and, generally, a Map get is fairly efficient - so property values stored there are more rapidly retrieved.
When first using Themes in combination with library controls, I was confused to find that my setters were never being called. If I was targeting the width property of a control with a Theme, for instance, I could see in the generated markup that the desired value was being applied, but there was no other indication that the property was being set. For example, if I added a logging statement to the setWidth() method, that logging statement was never triggered. I have since discovered that this is because, when a property is applied via a Theme, the resulting value is stored in the Map, not in the component itself. As previously mentioned, the renderer also doesn't access the getWidth() method directly; instead, it accesses the attributes Map. That Map's get() method calls getWidth() only if it needs to.
Naturally, this holds a couple implications as well:
This is the biggest reason Themes speed up rendering. If a renderer needs a component attribute, and that attribute has been set by a Theme, the value is retrieved in the most efficient manner possible. The attributes Map simply returns the value. The true component state is ignored.
Do not set a component property via a Theme if you need that property's setter to be called. One of the benefits of object-oriented programming is that object state cannot be touched directly: in order to modify - or even read - a state attribute, external code must call a method that performs the action on its behalf. This provides an opportunity for all manner of "behind the scenes" code to be executed, should the larger business process require it. This is the principle that prevents, for example, an employee's status from being changed from "active" to "terminated" without all sorts of other necessary business processes being triggered in response to that change.
IBM intended Themes to be used only for streamlining the definition of the visual attributes of a page. This is why, if you examine any of the standard themes that ship with Domino (such as the various OneUI variants), you'll see that they only modify visual component attributes, like styleClass. The more attributes you define only in a Theme, the faster your pages will load, both because the property is ignored during the first 5 of the 6 JSF lifecycle phases, but also because during the final phase, the value will be accessed efficiently. But if your business process is relying on awareness that a given attribute has been assigned a value, do not target that attribute with a Theme. The setter will never be called, so you will have no opportunity to respond to the value assignment.
locating XPage components with XspQuery
Sun, Apr 14th 2013 12:00a Tim Tripcony Several years ago, I wrote a utility Java class designed to make it easy to search for components within the current XPage instance based on various criteria. I've found it enormously useful, and, apparently, so has Keith Strickland, because he added it to org.openntf.xsp.extlib, complete with a few refinements. As an example of how you might use this, examine the following line of code:
List requiredFields = new XspQuery()
.loc [read] Keywords: ldd
your how is not your what
Wed, Apr 3rd 2013 11:36a Tim Tripcony I've noticed a pattern emerging when I'm asked for help with XPages. Here's a representative conversation:
"I'm trying to do [X] and it's not working. How can I do that?"
"What are you trying to accomplish?"
"I already told you. I'm trying to do [X]."
"No, that's how you're trying to do it. What are you trying to do?"
For example, replace "[X]" with "reach into a repeat control from outside it" (since this has become the most frequent topic I'm asked about [read] Keywords: xpages application
my new favorite quote
Sat, Mar 23rd 2013 5:20p Tim Tripcony "We go about our daily lives understanding almost nothing of the world. We give little thought to the machinery that generates the sunlight that makes life possible, to the gravity that glues us to an earth that would otherwise send us spinning off into space, or the atoms of which we are made and on whose stability we fundamentally depend. Except for children (who don’t know enough not to ask the important questions), few of us spend much time wondering why nature is the way it is; where the [read] Keywords: wiki
Taking the scary out of Java in XPages: Prologue
Tue, Feb 26th 2013 9:50p Tim Tripcony The discussion following my last post made stark the need for greater availability of information that makes the nature of Java more accessible to Domino developers. Credit for the title of this post goes to Declan, who is considering writing a series of blog posts on this topic. I will be doing the same; hopefully there will be a fair amount of duplication. As David Leedy is fond of stating, it's a good thing when several people share the same information, because that makes it easier for the [read] Keywords: domino
Passthru vs. component - my perspective
Sat, Feb 16th 2013 9:40p Tim Tripcony Paul Withers posted a thorough article explaining the differences between namespaced XPage components (e.g. ) and their corresponding passthru elements (e.g. ), providing numerous examples of what actually happens when these objects are constructed. I've always heard (and often repeated) that passthru elements are more efficiently processed than their namespaced equivalents, so Paul's post inspired me to offer my own perspective.
Simply put, there's practically no difference... but there a [read] Keywords: acl