A Siebel eScript framework



In my inaugural post, i'll attempt to tackle, probably one of the most talked about Siebel challenges around.

If you dont know what the ABS (ATI) Framework is, i highly recommend you have a look at the articles on Siebel Unleashed. One of the key features that it provides, is access to a global Class that provides an abstraction layer on top of eScript which allows you to do things such as:

TheApp.Get("Contact").GetFieldValueWithId("12323","Last Name");

This would normally take atleast 10 lines of code to query the BO, BC, get a value from application and add error handling, but the above abstraction does it in 1 line.

In this article, i'll provide a technique to implement a custom object with method chaining, but the million dollar question is how do we build a eScript Framework in Siebel.

Mike M. Lin showed us how to make a custom object available globally in Siebel, his solution was to reference the Application object and attach it to the Object constructor, like below.


Object.prototype.TheApp = this;

What this does is make TheApp available in every script without declaration. At this stage all we've done is made TheApplication() = TheApp.

Mike M. Lin also offers a custom BC method called GetFieldValueUpperCase(), which is applied to the Object constructor, the side effect of attaching custom functions to the Object constructor and calling Siebel methods on non Siebel objects or objects where the method dosnt exist, is you'll get an error.

The GetFieldValueUpperCase() method can be used on BC based objects such as GetBusComp

var oBC=TheApp.ActiveBusObject("Contact").GetBusComp("Contact");
//retrieve recordset
oBC.GetFieldValueUpperCase("Name");

But the same method is also available on every other object in the scripting engine.

var sDummy = "testing";
sDummy.GetFieldValueUpperCase("Name"); //Error

The problem is obvious, the complete solution needs to implement hirerachical method chaining in a class like fashion. This will allow us control what methods are available on what parent object. Since we do not know the Siebel constructors, we will do the next best thing, which is create our own Siebel class, which is what i think the creators of the ABS (ATI) framework have done.

The following code is a protoype that i've created, to emulate the ABS (ATI) Framework.


Object.prototype.TheApp = function () {
return {

Get: function ( sBC ) {

/***********************************************************************/
// Component Name : JLE eScript Class
// Use : TheApp.Get(BC Name)
// .QueryWithSearchExpr(Search Expression)
// .GetFieldValueWithId(Id, Field)
// : TheApp.debug(String)
// Date Author
// 20/02/2009 Jason Le
/************************************************************************/
TheApp.BC = sBC;
return {
QueryWithSearchExpr: function ( sSS ) {
var oBC = TheApplication().ActiveBusObject().GetBusComp( TheApp.BC );
oBC.ClearToQuery();
oBC.SetViewMode( AllView );
oBC.SetSearchExpr( sSS );
oBC.ExecuteQuery( ForwardOnly );
if ( oBC.FirstRecord() )
return oBC;
},
GetFieldValueWithId: function ( sId, sFldName ) {
var oBC = TheApplication().ActiveBusObject().GetBusComp( TheApp.BC );
oBC.ClearToQuery();
oBC.ActivateField( sFldName );
oBC.SetViewMode( AllView );
oBC.SetSearchSpec( "Id", sId );
oBC.ExecuteQuery( ForwardOnly );
if ( oBC.FirstRecord() )
return oBC.GetFieldValue ( sFldName );
}
}
},
debug : function ( text ) {
var fp = Clib.fopen("C:\\debug.txt", "a");
Clib.fputs(text + "\n", fp);
Clib.fclose(fp);
}
}
}();

TheApp.prototype.BC = "";


This class contains 4 methods
Get
Theoretically this would accept upto two parameters, the name of the BO and the BC, if only one parameter is passed in, we use the Active BO.

QueryWithSearchExpr
This method is chained of Get and returns a BC instance with the provided search expression.

GetFieldValueWithId
This method is chained of Get and returns a field value, with the provided row id.

debug
log to file function.

Examples of use.

var BC = TheApp.Get("Contact").QueryWithSearchExpr("[Id]='1-ABCD'");
TheApp.debug ( BC.GetFieldValue("Id") );

var Field = TheApp.Get("Contact").GetFieldValueWithId("1-ABCD", "Name");
TheApp.debug ( Field );


If you look carefully, you notice that the custom object acts as an interface to the Application() methods instead of referencing this on every Object. This allows us to avoid those errors, when we were using the non hierarchical methods.

A lot of complexity has been left out of this code to make it easier to read, it has been hard coded to work on the ActiveBusObject, there is no error handling, there is no consideration into preventing memory leaks, this point is especially important because if improperly implemented, either nothing will work, or when you go into production, it will bring your environment down.

With that disclaimer aside, this idea of creating a custom object structure allows us to be very creative and create our own eScript Framework on top of Siebel.



I know there are architects out there thinking, are you crazy to attach something to the Object constructor? I'll look into a possible concession with the framework, and offer an alternative implementation.

To find out what this means, stay tuned..




Reactions:

3 comments:

  1. Gr8 job JASON!! ... i didn't have time to work on it ... your work will definitely help!!

    ReplyDelete
  2. Good thinking outside the box. I like the work. This is exactly the kind of good community brainstorming I was hoping for when I posted that blog.

    On the downside, you won't be able to call custom methods directly from non-application objects (think, QueryWithSearchExpr() called from a buscomp server script on itself), which may not even turn out to be all that useful anyways. And on the upside, you've done away with the dangerous side-effects of extending the Object class.

    Good stuff.

    ReplyDelete
  3. Reader Lubomir wrote...

    "There is a possibility to extend Siebel Object too. So you do not need to create any generic object and you can add any function directly to Siebel Objects..."

    Thanks Lubomir, i hope you dont mind, but i've decided not to disclose the technique, because modifying the Siebel objects will have unintended affects on garbage collection.

    ReplyDelete