Disclaimer and License

Opinions expressed here by Tim Tripcony are his own and not representative of his employer.

Creative Commons License
Tip of the Iceberg is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at xmage.gbs.com.

Unless otherwise explicitly specified, all code samples and downloads are copyright Tim Tripcony and licensed under Apache License 2.0.

Search

What the Quote?

"It may be slow, but at least it sure is ugly."

Pete Oberlin

"If you love somebody, set them free."

Linus Torvalds

"If I can get the foot thing out of my head, then I can eat my potato."

Laura Tripcony

04/28/2012

quick tip: conditional event handlers

Category xpages
I was recently asked by a colleague whether a partial refresh event can be canceled during its execution - if, in other words, the code first checks whether the rest of the code is necessary or useful, and that check returns false, can the code then somehow prevent the refresh from occurring?

I told him that I didn't believe this was possible. The reason for my answer was that, because the standard event handlers in XPages use Dojo's XHR (XMLHttpRequest), what triggers the event in the first place is an Ajax request to the server; the client-side JavaScript involved assumes that the server will send back HTML that is representative of the result of the event's execution. Thus, whether or not the event code did anything useful, the contents of the HTML element that represents the partial refresh target will still be replaced with whatever HTML the server returns. So there is no way (that I am aware of) to cancel the event once it has already been triggered.

There is, however, a way to achieve the same result, and to do so even more efficiently: split the code execution into two distinct operations. To be precise, completely isolate the portion of the code that does what the event itself is intended to do from the portion that determines whether that action is even appropriate under the current circumstances.

All XPage components support a "rendered" attribute. If this attribute's value evaluates to a false Boolean result, the server will not send any representation of that component or its descendants (if any) to the request consumer. In the most common use case scenario, this means that, if a typical browser accesses a typical XPage, and that XPage includes a component that is not to be rendered, the HTML that would otherwise represent that component is never sent to the browser. The component still "exists" as part of the component tree for that page, so (all else being equal) its remaining attributes are still calculated during each request, and other components can examine its attributes if needed, but the user never sees that component... only any effects it may have on other components.

Because this concept is so similar to the notion of "hide-when" formulae in traditional Domino applications, this is once of the first concepts learned by an XPage developer, and is therefore almost universally known. What is arguably less known is that event handlers are actually components too. They have no visual representation in the HTML, but HTML is, in fact, sent: specifically, a single script tag typically encompasses a representation of all event handlers defined within the tree... a representation which consists of code that causes the browser to listen for each defined event.

Because event handlers are components, they, too, support the "rendered" attribute. And, as with all other components, if this attribute evaluates to a false value, no representation of the event is sent to the browser. Because the representation of each event that is not rendered would have been JavaScript that binds event listeners, if an event is not rendered, no JavaScript is sent for that event, so no event listener is ever bound... which means that, if the user performs an action that would otherwise have triggered the event, the event is not triggered.

So, to sum up, if some of your events are only applicable under certain circumstances, but you want the component to which the event is bound to display anyway, set the rendered attribute of the event handler itself to a value binding that calculates whether the event should fire, and set the event itself to just do whatever it should do if the event does fire. With this simple change, you can prevent any network traffic or server processing when the user clicks something that would not produce a useful result... just be sure to give them some visual indication that nothing is going to happen (e.g. link the component's styleClass to the same logic, causing the component to visually indicate that it is "disabled").

04/20/2012

LotusLearns wants you to think my content is theirs

Category ethics
It was brought to my attention today that LotusLearns.com has been aggregating all sorts of Lotus-related content (including some of mine) without obvious attribution.

Check out Nathan's post for more information.

If information that I share is useful to others, then I'm always happy to see it reach a wider audience. But our community has a pretty good track record of giving credit where credit's due, and it concerns me that LotusLearns is representing so much content as their own. For sake of comparison, look at the PlanetLotus home page, then look at LotusLearns.com, and decide for yourself which site makes it easier to identify where each article originated.

Of particular concern is that the very first link on the Downloads page is a full PDF of Mastering XPages. Either Miss Smith isn't screening the content she's aggregating enough to realize she is linking to an illegal copy of that publication... or she simply doesn't care.

UPDATE: the site is now gone entirely. Either it was voluntarily taken down or Google shut it down in response to the various copyright claims they received from my fellow bloggers. A word of advice to those considering adding aggregation features to any site: just ask. There's a cliche that states that it's easier to ask forgiveness than permission, but that tends not to hold true where copyrighted information is concerned. Contact the copyright owner in advance, explain your intentions and motivations, and just ask if they're cool with your plans for their content. If they don't agree, just don't do it. Even if they do agree, and later change their mind, respect that. They own that content, so it's their decision to make, not yours.

04/16/2012

why extensive use of Themes speeds up XPage execution

Category xpages themes
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):
  1. 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.
  2. 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.

04/13/2012

when to create reusable controls

Category xpages
Most of us understand why our code should be reusable, even if it isn't: keeping duplication of effort to a minimum, such as the capacity to apply a fix or enhancement once and gain distributed benefit. In terms of XPage controls, there is also a lot of information available about how to structure code to make it reusable. For instance, I recently submitted two guest tutorials to Notes in 9: an example of how to implement an in-view-edit Custom Control, and a demonstration of converting a Custom Control to a library component. Not much has been said, however, about when to make the effort of creating these types of reusable artifacts.

Many of us are busy. That's a very good thing... people want something from us, and they're willing to pay for the result. Not everybody can say that right now, so even those of us with unrealistic deadlines are comparatively fortunate. But, even in our haste to deliver what is expected of us, there should ideally be some balance that allows us to give our employers and customers their money's worth. And that can't truly happen unless we're structuring our code - at least a little bit - to be reusable.

So... amidst the tight timelines and pressure to deliver, when do we take the time to create these types of artifacts that may only pay for themselves in the long run? In my experience, there are two ideal opportunities to do just that: at the beginning of a project, and at the end.

Particularly when there are few (or no) live XPage applications in your environment, it can be difficult to identify potential areas of duplication. And, of course, regardless of how many applications are already in place, it can be difficult to convince project stakeholders both to pay and to wait for the extra time it may take to perform this manner of design analysis up front. So in many cases the only realistic opportunity to identify candidates for reusability is once the project is complete. Many organizations' processes include some form of "Lessons Learned" phase for each project (even if only in principle, not necessarily in practice). This can be an excellent time to review the end result to identify which portions of the design could be packaged for consumption in subsequent projects, thereby reducing both the cost of that subsequent development and the effort required to maintain all applications that consume those artifacts.

An even better time to do this analysis, however, is during the initial design phase of the project. In a sense, identifying what should be wrapped in a control and what should be page-specific is often easier to envision prior to actual development, because these are primarily structural decisions, not logical decisions. Put another way, in contrast to other reusable code, like script libraries, you don't have to map out the processes of the application to predict that its interface will include common features as users navigate from page to page. "Low-fidelity" prototyping (using tools like Balsamiq Mockups, Evolus Pencil, or even just pen and paper) is a great way to visually identify these areas of potential duplication prior to even opening Domino Designer. This makes it likely that, even within the scope of a single project, the application will be faster and cheaper to develop and easier to maintain. When extended across numerous projects, this process can drastically reduce total cost of ownership and implementation.

03/26/2012

Needle in the Stack Part 1: why Java is faster than SSJS

Category xpages stackoverflow
More and more XPage developers are turning to stackoverflow to seek community assistance with questions they have about developing XPage applications. This ongoing series will provide additional commentary and insights into the answers I have provided on the site that members of the community have found to be useful.

Part 1: Why Java is faster than SSJS

David Leedy asked, "Is there a performance hit in SSJS when using @Functions?"

If I want to parse a text field in SSJS there are 2 main tools. The built in JavaScript code and the newly converted @Functions. Are the @Functions slower then using pure javascript? Or is there no real difference?

viewScope.put("length", tmpStr.length)

vs.

viewScope.put("length:, @Length(tmpStr))

The short version of the answer is: yes, but barely.

@Functions in SSJS are not true @Functions the way we're used to thinking of them. In Notes client apps and non-XPage Domino web apps, @Functions are part of Notes Formula, a limited scope, highly optimized macro language. Execution of these functions occurs very "close to the metal", so to speak, so event code written in this language will execute very rapidly (assuming no other factors are at play, such as network lag when executing functions that trigger network transactions, logical flaws in the code that cause unnecessary complexity, and so on).

In SSJS, however, @Functions are simply... more SSJS. They're implemented in Java, but in order for that Java to run, the XPage runtime first needs to find the correct code to execute.

When an XPage application is built (in the Eclipse project sense of the term "build"... in other words, compiled), a Java class is generated behind the scenes by Designer. This Java class is stored inside a design note within the application. Hence, when the end user accesses an XPage design element, Domino isn't looking at the XML; it's running the Java class that was generated by Designer. The XML is just an instruction set that tells Designer what Java to generate. This provides a runtime performance benefit compared to, for example, the way browsers work: HTML markup is downloaded from the request target, the markup is parsed, and then the browser decides what to do in real time based on the result of parsing that markup. The advance compilation step undertaken by Designer allows the XPage runtime engine to follow a far more efficient process.

Practically every XPage contains at least one instance of Expression Language (EL). When viewing the XML source, you can easily spot instances of EL because it uses a recognizable syntax:

[load|dynamic]{[optional colon-separated prefix][expression]}

Here are a couple quick examples:

${database.title}
#{sessionScope.userTheme}
#{javascript:return tmpStr.length;}
#{javascript:return @Length(tmpStr);}

These expressions are occasionally also referred to as "bindings", because they are supported in two contexts: value bindings and method bindings. Method bindings are typically only used to define the code that should be invoked when an event is triggered; all other EL expressions are treated as value bindings. This simply means that the value of the component property that is bound to one (or more) of these expressions is not hard-coded. Some (usually, all) of the property value is calculated contextually at runtime.

Two portions of the EL syntax always have a direct impact on performance. The first is the initial character, which will either be a $ or a #. A $ indicates that the expression will only be evaluated once; expressions preceded by a # will be evaluated repeatedly. For Notes / Domino veterans, this distinction bears some loose conceptual similarities to the distinction between computed fields and computed-when-composed. In practice, each component property that can be assigned a value binding (and very few cannot) either does have a value binding or it has a "local value". Whenever any of these properties is accessed, the "getter" checks the local value first; if that value is not null, the value is immediately returned. Otherwise, it looks for a value binding associated with that property. If one exists, it returns the result of the evaluation of that value binding. Finally, if the property has neither a local value nor a value binding, null is returned.

Paul Withers posted a detailed explanation of the difference between the actual inner workings of $ / # value bindings. To sum up that explanation:
  • When a component is created, all properties defined on the XPage for that component are set immediately.
  • If the value is hardcoded, that value is simply passed directly to the property.
  • If, instead, it is a value binding, it follows one of two paths:
    • If a # binding, a ValueBinding object is created and associated with the property.
    • If a $ binding, the expression is evaluated immediately, and the resulting value is passed directly to the property.

That final bullet is why $ expressions are only evaluated once: by the time the component has been added to the tree, the property no longer has a value binding. It has a local value that is the result of evaluating a value binding. In case you're curious, this is also the reason why $ bindings are so sensitive to timing and sequence. # bindings aren't evaluated until the associated property is accessed; $ bindings are evaluted when the component is created. Hence, you can't refer in the property of a component at the top of the page to properties of a component at the bottom of the page: the component to which the value binding refers doesn't even exist at the time the value binding is evaluated.

The second portion of the EL syntax that always impacts performance is the optional prefix. The prefix tells the EL resolver how to interpret the expression. If you ever hear an XPager referring to "standard EL", they're most likely referring to expressions with no prefix; SSJS expressions are still EL. But they use the optional "javascript" prefix to tell the resolver to use a custom process to interpret the expression. This is where the performance differential occurs.

Standard EL packs a lot of punch into a very finite syntax, but that syntax is very finite. The string parsing required to determine what an expression "means" can be performed very efficiently. JavaScript, on the other hand, is an extremely complex language. Not only is it the only language in ubiquitous use today that supports the unusual pattern of closures, but like most programming languages, the same character can mean very different things based on its contextual position. One of the easiest examples of this to understand is the use of parentheses: they might indicate invocation of a function, or they might indicate custom order of operation; it's all about the context. If you're not in the habit of including semicolons and curly braces in places where the JavaScript spec indicates they're technically optional, even whitespace has meaning. There's even a scenario where whitespace can cause disasters even if all the semis and curlies are present, and the result is the difference between returning a fully defined object and returning a null pointer. Parsing all of this into something that runs as intended is a Herculean task, one typically only implemented by the various browser vendors.

To add insult to injury, regardless of the type of EL expression, its evaluation (or invocation) must all occur in Java. Again, that's fairly easy to do when parsing standard EL. For instance, variables are evaluated against the request scope, which essentially consists solely of doing an inexpensive get against a single Map. Once the pointer has been resolved, the XPage knows what Java object is involved, and its methods can be directly invoked. Babysitting variable scope in JavaScript is not nearly as straightforward. Similarly, all operations performed against each variable must be handled via equivalent Java operations.

XPages accomplish this language-to-language transition using what is known as an abstract syntax tree (AST). This creates an in-memory, language-independent description of the structure of the code. It establishes a distinction between constructs like literals (hardcoded strings, numbers, etc.), identifiers (variables), operators (+, -, *, /, etc.), functions, and other concepts that might exist in any programming language. For instance, the notion of scope is far less tangible than the notion of an operator, but is crucial to keep track of (and, in this case, tricky, partly because Java does not yet have native support for closure). Once the JavaScript has been converted to this language-independent representation, each portion of the tree can be paired up with a corresponding Java construct, and the expression can finally be evaluated.

In a sense, this means that, every time SSJS is evaluated, the XPage runtime is essentially "guessing" what Java we want to invoke. Admittedly, it's a pretty good guess... frankly, I remain a bit astounded at how faithfully IBM adhered to the JavaScript specification, and doing so means that you're not often going to have results that differ wildly from what you'd experience running the same JavaScript expressions within a browser (aside from platform-specific differences, of course: Firefox doesn't define a global "database" variable, and SSJS doesn't natively know what "window" means). But it's expensive to maintain that faithful adherence, not just in terms of product cycle, but, again, every time a page evaluates SSJS.

This entire process is actually very easy to understand just by thinking in terms of spoken language. Imagine you've hired an employee, but every instruction you provide them and every question you ask them must be delivered through an interpreter, because you don't know their language, and they don't know yours. At all. Every time you say anything, even "yes" or "no", your employee does not understand until the interpreter has repeated what you said in their native language. If your interpreter is very skilled, they will be able to convey precisely what you mean, because they'll know which figures of speech have a specific cultural connotation and cannot simply be translated word-for-word. But every time you use some colloquialism that doesn't directly translate, extra care must be exercized to ensure your employee doesn't end up doing something drastically different from what you intended. And no matter how simple each unit of communication, it takes at least a little bit longer because it has to be repeated in a different language.

The moral of the story, then, is that when you write your code directly in Java, your XPages don't have to "guess" what Java should be executed... it just executes yours. Otherwise it's translating the code you wrote into a completely different language before it can run, and your user has to wait for that to happen. That wait is typically measured in milliseconds per expression, but add enough expressions and enough users, and they'll notice a difference.

03/19/2012

the XPages Extension Library book is almost here

Category xpages
After more than a year of discussing, planning, writing, editing, reviewing, and mailing paperwork around the globe, it's almost here: the definitive guide to the XPages Extension Library is scheduled for publication effective May 9.

The official authors are Paul Hannan from IBM, Declan, Jeremy, Paul Withers, and myself, but we had help from quite a few others in the Domino community, including several IBMers, such as Niklas Heidloff... in my opinion, the content he provided that demonstrates just how easy the Extension Library makes integration between XPages applications and social applications such as Facebook and Dropbox will blow your mind. You've likely already seen some of the videos he's published that demonstrate this capability, but now you can obtain a comprehensive walkthrough of this type of integration in paperback form and keep it within arm's reach.

So here we are, just a few weeks away. It's an amazing book, and I'm incredibly proud to have played a small part in its creation. You can pre-order your own copy here. And, to be honest (personal bias notwithstanding), if you're a Domino developer, you probably should.

03/05/2012

upcoming X Series webinar: Climbing the Beanstalk

Category xpages webinar
This Wednesday, from 11 AM - 12 PM EST, I will be hosting the latest "X Series" webinar sponsored by GBS and TLCC:
Climbing the Beanstalk: a Gentle Transition from LotusScript to Java beans

XPages bring powerful new capabilities to the IBM Lotus Domino platform, but the development model is quite different from what most Domino developers are accustomed to. This webinar will take you on a gentle but rapid journey from the familiar territory of procedural LotusScript, through a common-sense approach to visualizing data and business processes as "objects", to a world in which those objects map directly to user interface components with which your users can intuitively interact. Don't discard everything you've learned in an attempt to embrace the new... instead, evolve what you already know: this session will show you how.

I volunteered to host this webinar because, when I presented an earlier version of this material at IamLUG last year, something fascinating occurred. Typically, when I'm presenting about XPages or other technologies, it feels somewhat one-sided: a couple questions might get asked during the presentation, perhaps a few more afterward, but this session quite rapidly became a conversation. The slides I'd prepared still served as a useful outline for the discussion, but it remained quite interactive throughout. I enjoyed getting the attendees' perspectives on the topic, as well as having real-time confirmation that what we discussed was interesting to them and potentially even useful. Having had time to reflect on that experience, I suspect the interactivity was facilitated primarily by the following factors:
  • The atmosphere of any user group conference tends to be less intimidating than Lotusphere for all concerned. IamLUG is no exception. I was rather relaxed, the attendees were relaxed, and I was at the same level as them in a small room, not up on a stage in front of 500 people. In this environment, the attendees are likelier to feel that I'm talking with them, not at them.
  • While the material included actual code examples, the bulk of the content was philosophical. This session isn't a "blast", where you take away 50 useful tips that you can immediately put into practice upon your return to the office. Rather, this is an analysis of why we do what we do, and an exploration of how some programming principles might be more effective than others in achieving those objectives. Everyone has a unique personality and different experiences, so it's only natural that this topic will resonate differently with everyone, so it lends itself better to an interactive discussion than a typical deep dive technical session.
  • Finally, XPage adoption has gained some significant momentum over the past year. Domino developers are exploring it in greater numbers, and those who have already been developing XPage applications for several years are starting to really dig in deep to discover some advanced capabilities. While this material isn't inherently limited to XPage development, as the fundamental principles are applicable to nearly all programming languages and application frameworks, embracing the mindset shift it encourages does make it easier to transition from traditional Notes development to XPage development. As such, no prior experience with XPages is required to benefit from this session; in fact, the further away XPages seem on your horizon, the more you stand to benefit from considering this material... the longer you've spent pondering and, hopefully, applying these principles by the time you do start developing with XPages, the more natural it will feel once you get there.

For all of those reasons, I suspect that the webinar format will be a perfect fit to revisit this material. You'll have an opportunity to ask questions throughout, to participate in a discussion about the merits and, yes, the challenges, in adopting a programming style that is more connected to the business it serves than the procedural approach that has dominated Domino for so long. I look forward to discussing this further with many of you on Wednesday. Register now if you plan to attend.

02/29/2012

determining the theme ID for any component

Category xpages themes
In XPages, themes target components by ID. Not by the value of the id attribute, but instead by two values specific to themes: themeId and styleKitFamily. All components that can be targeted with a control rule in a theme support "getter" methods for these two properties:

var component = getComponent("someComponentId");
var specificId = component.getThemeId();
var defaultId = component.getStyleKitFamily();


The themeId property, therefore, is the theme ID that is specific to a given instance of a component. For example, you might assign a themeId of "footer" to a panel or div. But any component that can have a themeId also has a "default" ID that all instances of that type of component share. This is what the getStyleKitFamily() method is for: determining what the base ID is for a given type of component.

One crucial behavior worth remembering is that assigning an individual component instance a specific theme ID does not overwrite its default, as is typical for most component properties; in the above scenario, therefore, assigning themeId a value of "footer" doesn't overwrite the component's default theme ID of "Panel"... if your theme designates control rules for each of these, this component will be impacted by both. All panels have a theme ID of "Panel", but some panels also have an instance-specific ID.

Because the default theme ID is such a handy thing to know, I've created a reference database that allows you to browse all known components by namespace (e.g. "xp" for core components, "xe" for Extension Library components) and find their default theme ID. You can ignore the "evo" namespace... that just shows up because I have the Transformer Extension Library installed on that server. Unless, of course, you're a Transformer customer, in which case you might find it useful to browse those components as well.

For additional convenience, you can download the reference database. Place it on any Domino server, and the namespaces it lists will reflect whatever component libraries are installed on that server. By the way, the reason it's using the "oneuiv2" theme and not "oneuiv2.1" is because, in my testing, the component registry API it uses seems to be broken in 8.5.3, which is why the live demo link points to XMage and not Frodo; the former is still running 8.5.2, while the latter has been upgraded to 8.5.3. So please let me know if you experience the same issue. IBM tells me it's working fine in 8.5.3, but that's not what I'm seeing...

02/27/2012

XPages Portable Command Guide is a book every Domino administrator should read

Category xpages
Yes, you read that right: every Domino administrator should read the new XPages Portable Command Guide. Developers should too, but from what I've read so far, I feel it's more crucial that admins pick up a copy of this book.

Let's assume that you're a diligent administrator. You've known for maybe a decade now (or more) how best to configure an end user's Notes client installation. You can set up an efficient replication and mail routing topology in your sleep. You've even kept current, so you now know all the best practices for configuring DAOS and Traveler. Congratulations! You're a top notch email administrator.

But if I'm your Notes developer, and I need you to deploy a new XPage application, do you know what questions to ask me in order to ensure that the correct persistence settings are enabled in the application's xsp.properties file? Do you know what heap size should be set in the server's INI to provide a solid balance between performance and scalability? It's fantastic that you know exactly how to support every last detail of an email environment, but do you know how to support applications?

If you don't, or you're not sure, or even if you think you're sure, buy this book. Sorry for the blunt honesty, but I haven't met a single Domino administrator who could instinctively tell me what the xsp.persistence.mode setting should be, based on whether the users want the application to be fast, scale to massive amounts of concurrent users, or provide a healthy compromise between the two. If, at a minimum, you can't answer that question without even stopping to think, and you administer production Domino servers running 8.5, or ever plan to, you need this book.

Hint: the answer is on page 24. In fact, the entire first chapter - all 81 pages of it - are just about how to configure one file: xsp.properties. This is where you define, either at the server level, or at the application level, or both, resource management (such as CPU and RAM), cache management, and the like. There are plenty of settings that can be defined in this file that only the developer should care about, but many of them you don't want the developer to decide. Trust me, if you leave it to me, I'm typically going to max out the RAM consumption in an attempt to provide lightning fast response times. But it's your server. You should be overriding me on that decision... as long as it's still in keeping with the end users' business needs, of course.

Chapter 2, with the exception of a couple pages at the end about defining very specific security settings, is also about a single file - notes.ini - for tweaking stuff like Java heap sizes and improving post-restart performance by preloading certain JVM tasks. Again, pretty much all admin stuff. Developers should also understand these things, or we won't be writing efficient code, but it's the administrators who need to know what the appropriate settings are based on the hardware available and the users' needs.

Chapter 3 is all about Domino console commands. Very useful for the developer when doing unit testing, but obviously this is still primarily targeted at the administrator.

Okay, admins, the second half of the book would probably just bore you. So feel free to move along now. But buy the book, okay? Your end users would love for their admin to know how to support their apps as well as their mail, even if they don't realize that's what they want. Trust me on this.

Developers, still with me? Good, 'cause we're getting to the half of the book you'll actually find interesting.

Chapter 4: Working With the XSP Client Side JavaScript Object. If you've been aching for documentation on this side of the tracks, here it is, and quite densely packed at that.

Chapter 5: Server-Side Scripting. This chapter digs slightly deeper into the server languages like SSJS and Java than Mastering XPages did, but honestly I didn't see a whole lot new here. On the other hand, this is, after all, a "portable command guide". So whereas, in the words of one of the authors, Mastering XPages was about the "journey" of learning to develop XPages applications, this is kind of the "yellow book" (for those of you who have been around a while) for XPages: the handy reference you keep conveniently next to your mouse pad at all times.

Chapter 6: Server-Side Debugging Techniques. This is where it gets really interesting. A loose form of some of this has already been distributed in PDF form with the XPages Extension Library (the actual library itself, not the next book about XPages that I'm going to tell you that you should buy), but this provides the same information in a more polished form, as well as much more detail. Spoiler alert: once you've finished this chapter, you'll know how to bind your test server's HTTP task to an Eclipse debugger, so you can step through your code just like you used to do with LotusScript. Mood killer: that does you no good if you write all your code in SSJS... you only get step-through for your Java code. Sorry. Take it from a guy who used to hate Java: just get it over with and learn Java. You'll write better code, your XPage apps will run faster and be more powerful, and your skills will be more portable should you ever decide (or be forced) to seek employment outside of the Domino microcosm. If your experience at all resembles mine, after a few months you'll wonder why you ever liked LotusScript. *

In summary, this is an excellent read for developers and admins alike. It's not as sprawling an epic as Mastering XPages, but it's not meant to be. This is a reference guide, something you'll want to absorb as much of as possible, but should keep on hand to revisit as the need arises.

* I am still fond of JavaScript, just not as enamored with it as a server-side language as I used to be.

02/24/2012

forcing component serialization in JSON-RPC methods

Category xpages
I'm a big fan of the JSON-RPC (a.k.a. "Remote Services") component from the XPages Extension Library. If you've ever asked, "how can I call server side JavaScript directly from client side JavaScript?", this component is the answer to that question. Not only does it make it incredibly easy to define a remote API for your client side JavaScript to interact with, it's also wicked fast.

One reason it's so efficient, however, is that it skips the standard view serialization. Remember, when I talk about views in relation to XPages, I'm almost always referring to the V in MVC, not the Domino index design element. In 8.5.2 and above, the default page persistence setting is to "keep pages on disk". When this option is selected (or left as the default), one of the last operations performed when a user accesses an XPage is serialization of the component tree hierarchy to the server's temporary folder on the local hard drive. Everything that the server knows about the page state - values of fields, properties of read-only components, etc. - gets flushed to flat files on disk, allowing the server to "forget" all of that... literally: once written to disk, it can be removed from memory.

If the user triggers some event against the rendered instance of that page, the request parameters sent to the server include enough information for it to locate that state information on its hard drive and parse it all back into memory. Assuming your server has post-millennial hardware, this all still typically happens in a matter of milliseconds, but there is an incremental lag caused by the disk I/O, which is the price paid for increased scalability; the alternative to this process is to hold all these page states in memory, so the more concurrent users you have, the sooner your RAM would vanish. If you've got enough RAM, of course, you can change the default behavior to an alternate option with more rapid response time. Changing it to "keep pages in memory", for example, forgoes serialization entirely. This causes events to fire more rapidly, because the server "remembers" the full page state (because it's still in RAM), so it doesn't have to go to disk to reconstitute the component tree prior to responding to the event. As a consequence, however, the state of all these pages lingers in memory long after each ceases to be needed.

The compromise setting is to "keep only the current page in memory". When this option is selected, the server only stores one component tree at a time for each user. When a user accesses a page, it renders the markup, but leaves the view state in RAM. Every event fired against that view instance is accessing that in-memory component tree state. As soon as the user navigates to another page, it serializes the previous page to disk, then constructs the new page in memory (and leaves it there until the next navigation event). If the navigation to a new page was not the result of leaving the page, but instead loading a different page in a new browser window (or tab), then it's conceivable that the user might close that new window and continue interacting with the original page. In this scenario, the server is then able to reconstitute the state of that page using the same process it would follow were it keeping all pages on disk. If, however, it was a typical navigation event (moving from one page to another within the same window), then the state of the first page will never be needed again. It's still there on disk, but will get automatically flushed once the user's session expires. In my opinion, this setting should be the default, because it provides excellent per-page performance without wasting RAM.

Because the default option is to keep all pages on disk, however, it is important to realize how this impacts the behavior of any JSON-RPC services you define. This type of service seems designed primarily for operations that are independent of component state. For example, I might wish to pass an employee's name or user ID from client side JavaScript and return a slew of details about that employee (job title, supervisor name, contact information, etc.). When any RPC method is called, the server needs to load the component hierarchy in order to know how to invoke the method, but there's no reason to save an updated instance of the component state once it's done so... we weren't posting new field values, or even running any events, just calling some remote code defined inside the XPage. So even if the method invoked has data impacts (e.g. send an email, close all tasks associated with the current document, etc.), it skips the serialization step entirely, because it assumes that no material changes have been made to the component state. And that's almost always an accurate assumption.

But what if it isn't? What if the behavior of your RPC method does alter the state of a component or values in a data source? If your application keeps the current page (or all pages) in memory, it doesn't matter, because whatever changes you're making are altering the in-memory view state, and any subsequent events will access that same in-memory state. But if you're using the default option to keep all pages on disk, because all RPC methods skip the step that saves the component state, your changes are lost... unless you force this serialization to occur anyway. The good news is that, while this might sound complex, it's quite easy.

In any RPC method that does make changes to component properties or data source values, at any point after all of those modifications are complete, add the following operation:
var app = facesContext.getApplication();
var stateManager = app.getStateManager();
stateManager.saveSerializedView(facesContext);
This forces the current view state to be written to disk, just as it would during a normal event. Ergo, any subsequent event is interacting with the page as you last left it, with any changes made by the RPC still intact.