Yesterday evening I got involved in an XPages conversation. It started with this tweet from Chris Toohey:
Dr Marky Roden then brought me into the conversation, just as I looked on Twitter! A bit of a conversation then ensued, which is shown below.
As I said, I needed to do more investigation on all scenarios. I want to thank all those who got involved in the conversation for moulding this blog post. I’m a firm believer that the only stupid questions are the ones kept inside your own head, because the chances are someone else wants to ask the same question – either today or in the future – and none of us learn except by asking questions.
The summary is every had good points to make and there are also a number of misconceptions. I’ll admit that I also had some misconceptions. The best approach will depend on the circumstances and a good understanding of what’s happening under the hood and how you can tune XPage components.
First Example – BR Tags
First, the key is to remember that although you type into the XSP Editor, with its design pane (the GUI interface) and the source pane (the XML interface), none of this is parsed by the XSP Command Manager, the server (or Notes Client) component that pumps out HTML to the browser. XPages get compiled down to Java classes, which can be found in the Package Explorer under the Local > xsp folder. This is key to answering Brad’s query about whether XPage components are more for the server to process. I’m starting off with the most basic of examples – a br tag and the XPages Line Break control – an example that I had in the bonus sections of the sessions I did at BLUG, DanNotes and UKLUG last year. The Line Break control is not visible in the palette by default, but you can click on “Other…” in the controls pane or right-click and customize the palette to show them.
If you use the code in the “HTML vs XSP” example and look at the Java class generated, this is what you’ll see:
Even if you’ve never written Java, it’s not hugely difficult to see what’s going on here. The HTML br tag – the first method, createBr – creates a new UIPassThroughTag object and calls the setTag method of it. The XPages Line Break control just creates a new XspLineBreak object. I’m not able to drill down into the UIPassThroughTag and XspLineBreak objects, so I can’t say what the impact on the server processing is. But if you look at the HTML output, it’s identical.
Second Example – Split Tags
So we know that even “pass-thru HTML” is an XSP component as far as the server processing is concerned. What about if you split tags, so an HTML div with an XPages Computed Field control inside it. This is where I was going with my final tweet (and I was wrong!). My expectation was I’d get two UIPassThroughTags, one either side of the Computed Field control. But instead, if you use the code in the “HTML vs XSP Split” example and look at the Java code, there are only two methods for the HTML/XSP version and also for the XSP only version.
When I looked at the Java, it makes total sense, because the UIPassThroughTag writes out both the opening and closing tag for the HTML div. Because I remembered that every component on an XPage comprises three core methods – encodeBegin, encodeChildren and encodeEnd. The encodeBegin method write the opening div tag. The encodeChildren method runs through any components inside the current one, so in this case the Computed Field control. The encodeEnd method closes the div tag. The encodeChildren method is basically recursive, running down through any child components and any children of those those children etc.
Third, Fourth, Fifth Examples – Multiple HTML Tags
But that realisation made me take it further than I would have done otherwise. With encodeBegin, encodeChildren, encodeEnd all handling the opening and closing of a single tag, what happens if you have an HTML tag within another HTML tag? This is where the third example piece of code comes in, “HTML vs XSP Multiple”. If you look at the Java code, you’ll see this:
Using HTML still spits out two methods in the Java, one creating a UIPassThroughTag object and one passing through a UIPassThroughText object. That makes sense, because the encodeChildren needs to add the static text.
But here we’re seeing two different Java classes used, UIPassThroughTag and UIPassThroughText. What happens if you modify the HTML to add a span tag immediately inside the div tag and around the text – effectively reproducing the HTML output from the XPages version, because a Computed Text control wraps its content in a span? Try it, look at the Java code and you’ll see this:
Just because the div and span are both tags, it still needs to create two UIPassThroughTag objects. That’s compared to two Java objects for the XPages Div control and the XPages Computed Field control. Some developers may feel this is bad, but it’s the safest mechanism to handle the flexibility of what XML could be put on the source tab of an XPage. If I were building an interpreter for that, the one constant and certainty is that every opening tag has a closing tag, so the easiest way to keep build time to a minimum and be certain you’re going to create Java code that works is to treat any XHTML tag as a single Java method, so separating out createDiv, createSpan and createText.
Take that a step further and use the “HTML vs XSP Multiple More” code. That has a div, a span, some static text, a br, and some more static text. If you’ve understood what’s gone before, you should be ahead of me already. You should already be expecting a UIPassThroughTag obejct for the div, a UIPassThroughTag object for the span, a UIPassThroughText object for the first bit of text, a UIPassThroughTag object for the br and a second UIPassThroughText object for the second bit of text. Compare that to the two XPages controls, with two Java objects resulting. Here I get the same output, this time using proper passThru HTML – a br tag within the value property of the Computed Field.
So if you want to write lots of actual HTML on an XPage, a Computed Field control may be an alternative method to minimise the Java code running on the server but still better control the HTML output. Of course the downside, as ever with any passthru HTML, is it’s harder to debug and there’s no validation that your HTML is correct!
Sixth Example – Taming Computed Fields
But as Dr Marky Roden says (trust him, he’s a doctor!), the XPages controls throw out more than you may want and the div control generates an ID. But there’s a way round that, with functionality that was added in 8.5.2. Computed Field controls have a tagName property. So to output a div but avoid the ID being generated, use the code in “HTML vs XSP Multiple Minimum”. This has the same HTML part as in “HTML vs XSP Multiple More”, with five Java objects resulting. But the XSP version has had the XPages Div control removed and the Computed Field has tagName as “div”. As you see below, you just get one Java object for the XSP version.
And if you preview it in a browser, you no longer get a span around the Computed Field, but instead it generates a div, because this is the tagName property.
Summary
So hopefully now you’ve now got a more in-depth understanding to enable you to control the server processing and HTML output. More importantly, thanks to the questions and discussion on Twitter, hopefully most of you have learned something. I know I certainly have.
Excellent post! Thank you for taking the time to do this analysis. It’s interesting to see the components that get generated. Ultimately, I guess the performance aspect would depend on how much work is done to instantiate a UIPassThroughTag object compared to an XspDiv object, for example. My assumption was that there would be more work to populate the properties (e.g. generating the ID) of an Xsp component as opposed to the pass-thru tag. Regardless, it’s important to realize that it’s still generating components for even this simplest of pass-thru HTML.
Hrmmm… I wonder if it would be worthwhile to create a component for an “inlinePassThru” that required that the developer take responsibility for opening and closing tags themselves. So basically it would have an empty encodeEnd block, and instead simply stream whatever HTML it found directly into the rendered output?
Alternatively, what about a “blockPassThru” component that took a List of HTML container tags and handled starting and stopping them as a group. That might streamline certain nested div/span situations.
Either way, I would contend that all of this is navel-gazing. If your XPages have bottlenecks, it’s not in whether your generated Java code has components with a few more layers of abstraction. Java bytecode is very fast. If there are substantial improvements to be made it’s going to be by 1) reducing the NSF I/O required for your application; and 2) reducing the amount of markup you’re sending/receiving with each request.
In other words, the problem is ALWAYS with the wire. 🙂
Yes, I agree and I need to blog about minimising the HTML as well. That’s another learning curve. And thanks also to Tim Tripcony for this follow-up as well http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-94Z52Z