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 timtripcony.com.

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

Search

« JavaScript literals | Main| the reason panel data sources can't be accessed outside the panel »

quick tip: persistent query string parameters

Category xpages
Here's a handy bit of code to drop into the afterPageLoad event of your XPages:

viewScope.putAll(param);

Why?

One of the best characteristics of XPage applications, in contrast to their non-XPage Domino counterparts, is their statefulness. The capacity to maintain consistency of data, user behavior, and user preferences between interactions with the "current" page, across pages within an individual user session, and even across all (or select groups of) users of an application is simply baked into the platform. This type of consistency no longer requires complex and fragile hacks.

Now that I've been developing XPage apps for almost exactly five years, I've come to take this statefulness for granted so much that I occasionally assume some portion of the XPage runtime is even more stateful than it actually is. Consider, for example, the query string parameters of a URL: at first glance, it might seem reasonable to bind some component or data source attribute to a specific parameter; e.g.:

#{param.preferredExportFormat}

You load the page to test it, passing some representative value via the specified query string parameter, and everything looks like it worked, as you'd naturally expect... until, that is, you trigger any event against that same page. Suddenly the attribute you bound to the parameter is gone. Why? You can see the parameter right there in the address bar... you know it's there. Why did Domino forget the value just because you triggered an event?

The more astute among you already know. Several of you might even be chuckling, and with good reason. Domino "forgets" the value because every event has its own query string.

Caveat: this might not apply to Domino 9. In a few quick tests on a server running XWork 9.0, I noticed that partial refresh events do pass any parameters from the original page load to any event in addition to the standard parameters, like $$ajaxid. So even this hack might not be necessary to achieve the intended result, at least if you've already upgraded to 9. And you really should.


Anyway, the afterPageLoad event is only run when a component tree is initially constructed. If the user triggers events against the page (links, buttons, etc.), that initial event is not fired again. So this is basically the opposite of the afterRestoreView event, which does not fire when the page first loads, but does fire when any user event occurs. As a result, in the context of any afterPageLoad event, the query string parameters the server is aware of are the same parameters that the user sees in their address bar. Hence, the line of code at the beginning of this post takes all entries (in the Java Map.Entry sense) from param and copies them to the viewScope.

So, instead of the previous, potentially fragile, example:

#{param.preferredExportFormat}

I now have a safer alternative:

#{viewScope.preferredExportFormat}

If that property name wasn't in the original URL query string, the above expression will still return null. But... if it was in the query string, the above expression will remain valid no matter how many events are triggered against the page instance... as long as nothing else clobbers the duplicated pointer in the viewScope, of course.