Thursday, January 10, 2013

Siebel Open UI Extensibility Part 1: Presentation Model

There is much to write and say about Siebel Open UI, the latest alternative to the somewhat dusty and - dare I say - doomed High Interactivity client (Internet sources tell us that support for Microsoft IE 8, which is the final supported IE version for Siebel's ActiveX-based HI client is trending downwards).

For Siebel developers, one of the most challenging area of change that comes with Open UI is the new JavaScript framework for UI-driven extensibility.

As discussed in a previous post, the Open UI client architecture relies on JavaScript libraries from Oracle and third parties, namely jQuery.

In this small series, I would like to contribute to the community learning curve by exploring the capabilities and recommended practices for Siebel Open UI extensibility.

Before we dive into practical examples, let's have a look at the scripting architecture of Siebel Open UI.

As discussed in the previous post, the customizable parts of the architecture are the presentation model (discussed in this article) and physical renderer (discussed in the next article).

Basically, when you wish to implement a certain UI-driven behaviour, you would have to write your own presentation model and physical renderer files and associate them with the applet of your choice. These files must define a class (let's call it a 'class' for brevity, although there is no class concept in JavaScript) which implements the required behaviour and inherits the proper base classes (usually from the pre-defined Siebel framework).

Here is the beginning of a typical presentation model extension file:

Click to enlarge
But let's have a look at it line by line. The following list describes the mandatory code to implement a proper Open UI extension file.

1. Verify that the new namespace does not yet exist

To verify that the new namespace for our customization doesn't yet exist, we must wrap its definition similar to the following:

if(typeof(SiebelAppFacade.myClass) === "undefined")
{
      //all other code
}

The above code ensures that the remainder of the code is only executed if the namespace myClass (our new class) is not yet defined within the realm of SiebelAppFacade (which is a generic class used in the Open UI framework).

2. Add the namespace

The following code adds the new namespace to the framework.

SiebelJS.Namespace("SiebelAppFacade.myClass");

The SiebelJS class is provided by the framework. Its Namespace function adds the new class.namespace definition to the SiebelApp parent class.

3. Register the class constructor

The third line in a typical Open UI extension file is very important and looks similar to the following:

SiebelApp.S_App.RegisterConstructorAgainstKey("myClassPM","SiebelAppFacade.myClass");

The RegisterConstructorAgainstKey function takes two parameters. The first one is the value of the Presentation_Model user property (or entry in a mapping file) for the applet or view definition. We will talk about the applet user properties (and the mapping file) involved in Open UI later in this series. The second parameter is the name of the new class.namespace definition.

4. Define the new class

The following is the wrapper function for the new class definition proper:

SiebelAppFacade.myClass = (function()
{
      //remainder of class implementation 
      return myClass;
}());

As you can see, the class itself is the return value of a function, which is a typical way of implementing classes in the non-class(y) environment of JavaScript.

5. Write the class constructor

Now comes the class constructor within the new class body function:

function myClass(proxy)
{
      SiebelAppFacade.myClass.superclass.constructor.call(this,proxy);
}

Typically the only line needed in the constructor function is the call for the superclass' constructor as shown above.

6. Extend the framework

Now it's time to use the SiebelJS.Extend function to add our new class to the framework and inherit all methods from it. The following line is from a presentation model file:

SiebelJS.Extend(myClass, SiebelAppFacade.PresentationModel);

7. Write the public Init function

As per the documentation, implementing the Init function is mandatory (for the presentation model, which is our worked example). The following lines create the Init function and the first line within it calls the superclass' Init function.

myClass.prototype.Init = function()
{
      SiebelAppFacade.myClass.superclass.Init.call(this);
      //remainder of code
}; //don't forget the semicolon here because it's a statement, not a function

8. Add properties and methods

The purpose of the Init function is mostly to define the remaining properties and methods which will be used to implement the desired functionality.

The following is example code:

this.AddProperty("ShowJobTitleRelatedField","");
this.AddMethod("ShowSelection",SelectionChange,{sequence:false, scope:this});

The AddProperty function adds a property (a name-value pair) to the framework. Later on, we can use the Get function to read the property value.

The AddMethod function defines a new private member function as part of the framework. The first parameter identifies the method within the framework. If the method already exists, then your implementation will practically extend the pre-defined method. Such is the case with the above example; ShowSelection is a predefined framework method which is invoked every time a record is selected.

You can also add your own methods. If you do so, you must later use the ExecuteMethod function to call your method.

For a complete description of all public classes and methods of the Open UI framework, refer to the Configuring Open UI guide in the Siebel bookshelf.

Bringing it all together

I know this is a lot of mind-boggling JavaScript magic going on here (at least for me). But it should be fairly easy to save the following lines as a boilerplate for a custom Open UI presentation model:

if(typeof(SiebelAppFacade.myClass) === "undefined")
{
//add namespace
SiebelJS.Namespace("SiebelAppFacade.myClass");

//register constructor
 SiebelApp.S_App.RegisterConstructorAgainstKey("myClassPM","SiebelAppFacade.myClass");

SiebelAppFacade.myClass = (function()
{
        function myClass(proxy)
{
SiebelAppFacade.myClass.superclass.constructor.call(this,proxy);
        }

//extend the framework
SiebelJS.Extend(myClass, SiebelAppFacade.PresentationModel);
     
//Init function
myClass.prototype.Init = function()
{
        SiebelAppFacade.myClass.superclass.Init.call(this);
        this.AddProperty("myProperty","");
this.AddMethod("ShowSelection",OnSelectionChange,{sequence:false, scope:this});
//additional properties and methods go here
        };

//private member function implementation (for OnSelectionChange) goes here

return myClass;
    }());
}

In the next part of the series we will see that physical renderer files are quite similar and I will use a simple example to show how to implement a UI-driven requirement using the Siebel Open UI framework extensibility.

have a nice day

@lex

3 comments:

Siebelish said...

Thanks @lex for breaking ice.

Regards,
-Rahul-

Alexander Hansal said...

cra-aa--ack

;-)

Chandradeep said...

This was really a wonderful article Alex. It really motivated me to start configuring Open UI which is looking like a herculean task for developers to customize !