wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Application Configuration / Parameters in XPages


Any application of reasonable size has parameters that configure it. Be it the salutations, the names of departments or the task priorities. In classic Notes and Domino application you typically find @DBColumn, @DBLookup or @GetProfileField to retrieve these values. Short of @GetProfileField you could do the same in an XPages application. However I would advocate a different approach. These are the steps:
  1. Create a SSJS script library. Call it "ApplicationConfiguration[ForNameOfYourApp[Group ] ] "
  2. Create one JavaScript object (see source below), call it "[ NameOfApp ]Config" (e.g companyConfig)
  3. Create inside this object functions that start with get and the Parameter you want to retrieve (e.g. getDepartments)
  4. In your application you then include that library and simply use the object with its function (e.g. companyConfig.getDepartments() )
What you do inside that object isn't that important for this approach. It is of course important for maintainability, performance etc., but that's a story for another time. So you can stick to your @DBColumn or @DBLookup for starters (until you learn better). So why would you want to follow that approach? There are 2 reasons: abstraction and flexibility. Inside your XPage you have an uniform way to access parameters without risking that 2 script libraries have an identically named function (e.g. getLocations() where one retrieves sales locations and the other manufacturing locations) that clash. The object name will help to distinguish them. Furthermore the call to the function is independent from the actual implementation. Doing a @DBLookup/@DBColumn for rather static values might not make a lot of sense, so some caching might make sense. Instead of building that into every page you can leave that to the function -- adding caching or reading config values differently will not change its signature (signature is the fancy way of saying: how it is called and what it returns). There is an additional reason why you want to stick to the " getParameterName()" syntax. It will allow you, if you want to, to replace your SSJS object with a managed bean that allows you more flexible options how to retrieve and cache your parameters. With a managed bean you also could use parameters directly in XPages' expression language (EL). You gain the option instead of writing #{JavaScript:companyConfig.getDepartments()} the more compact and understandable EL syntax #companyConfig.departments}. As said: only if you want to. Sticking to that syntax i SSJS doesn't have, as far as I can see, any substantial drawback. Planning for that keeps your options open.
As usual YMMV.

Sample parameter library
: Updated the sample a little since writing back of the cache was missing and a java.util.Hashmap seems to be more useful than {}
var companyConfig = {
   
    getDepartments : function ( ) {
       
        var cache = this. getCacheObject ( ) ;
        var result = cache. get ( "departments" ) ;
        if (result == null ) {
            // Here is where you would do @DBSomething or worse
            result = @DbLookup ( "configDB.nsf" , "configView" , "departments" , 2 ) ;
            cache. put ( "departments" ,result ) ; //Cache it back
            sessionScope. put ( "companyConfig" ,cache ) ; //Put the variable back in the scope
        }
       
        return result ;
    } ,
   
    /* Traffic light colors don't need to be cached */
    getColors : function ( ) {
        return [ "red" , "yellow" , "green" ] ;
    } ,

        /* Here would be much more of these functions */


        /* Utility functions for cache management */
   
    /* Retrieves the configuration object from a cache store.
       There are many ways to do that */

    getCacheObject : function ( ) {
        // Consider carefully where to cache. Typical places
        // are sessions or applications
        var curCache = sessionScope. get ( "companyConfig" ) ;
        if (curCache == null ) {
            curCache = new java. util. HashMap ( ) ;
            sessionScope. put ( "companyConfig" ,curCache ) ;
        }
       
        return curCache ;    
    } ,
   
    /* Resets the cache */
    reset : function ( ) {
        var curCache = new java. util. HashMap ( ) ;
        sessionScope. put ( "companyConfig" ,curCache ) ;
    }
}

Posted by on 20 September 2010 | Comments (6) | categories: XPages

Comments

  1. posted by Wayne Sobers on Tuesday 21 September 2010 AD:
    I guess a variation on this would work for LotusScript library and Normal notes client apps also.

  2. posted by Nathan T. Freeman on Tuesday 21 September 2010 AD:
    @2 - Except that 1) there are no session or application scoped variables in Lotusscript (unless you're very, very adventurous); and 2) there is no easy use whatever variables you do have for control-binding. So you can't set a keyword list to a Lotusscript call, or set the collection for an embedded view via an LS method.

    So there's really very little point in doing this stuff in Lotusscript.
  3. posted by Wayne Sobers on Tuesday 21 September 2010 AD:
    @3 - I've only ever developed for the Notes Client and certainly nothing that would require session or application scoped variables. I was thinking more alone the lines of encapsulation and hiding complexity, having to go to only one library/function to find "config" related information.
  4. posted by Patrick Picard on Tuesday 21 September 2010 AD:
    Excellent post
  5. posted by Nathan T. Freeman on Sunday 26 September 2010 AD:
    @4 - Oh, I bet you've written hundreds of things for the Notes client that, while not REQUIRING Session or Application-scoped variables, sure would have worked better if you had them! Emoticon smile.gif Every time you put a @DbLookup into a keyword list calculation, for example, that could be made much more efficient with a session variable.

    And how many times have you made copies of views where the columns are the same but the selection formulas are different, so you could show different data sets in, say, an embedded view? With XPages view & repeat controls, there's no need to do that. You can just build your ViewEntryCollection dynamically and then hand the collection to the control object.

    These kinds of features are some of the reason that, even if you're still deploying in the Notes client, designing your app in XPages makes way more sense. Especially now with the XPages Extensibility Library being available on OpenNTF.
  6. posted by Mark Barton on Wednesday 24 November 2010 AD:
    Stephan,

    Is this the approach you would take to replace all of those hidden fields you would use in classic Domino development to store reuseable information?

    e.g. Got a field which based on the specific sub domain calculates a site prefix which is then used throughout the page. NB this page is not bound to a data source.

    If I have a background image for a div which changes based on this site prefix I could then just refer to javascript object property which holds this value.

    This means my first step when converting a classic Domino app is to take any reference fields and convert them to SSJS - right?