ABS Framework - Prototype Library

[What is a Prototype?]

Using the prototype object is common in web development circles, but it is foreign to most experienced Siebel professionals.

This is the definition of “prototype” object according to Siebel Help
    An object prototype lets you specify a set of default values for an object. When an object property that has not been assigned a value is accessed, the prototype is consulted. If such a property exists in the prototype, its value is used for the object property.

    Object prototypes are useful to be sure that every instance of an object use the same default values and that these instances conserve the amount of memory needed to run a script. Then every instance of the object use the same function instead of each using its own copy of it.


That is quite an abstract description, and although it tries to explain the concept using a generic example, it still feels very disconnected.

In layman terms, using the prototype statement allows developers to add properties and methods to all instances of custom and pre-built objects in eScript/browser script (excluding Siebel Objects).

    So how do we use prototype to solve real world Siebel problems?

[ABS Prototypes]

The ABS framework includes prototypes to reduce the daily scripting chores for Siebel professionals. In this article we look at the some of the most interesting prototypes in ABS, and see how it can make our lives easier and more fun.

The ideas for these prototypes comes from years of experience and tideous hours of work to encapsulate the common routines that Siebel configurators and Integration people can share in one common library.

Array.IsIn

There are a lot of times when we want to compare the current active view, to a list of predetermined views, before performing some action.

Normally we have to write code like this to achieve it

var sViewName = TheApplication().ActiveViewName();

If (sViewName == “View1” || sViewName == “View2” || sViewName == “View3”) {

}

ABS provides us with IsIn() to achieve this same functionality in a more elegant manner.

var aViewName = [“View1”,“View2”,“View3”];
if (aViewName.IsIn(TheApplication().ActiveViewName()) {
}


This function returns a Boolean, indicating whether a value exists or not, but also returns an additional property that points to the index of the matched value.

Date.ToISO

ToISO() is useful for formatting dates to ISO format. This is commonly used to convert dates, so it can be easily sorted alphabetically.

var oDate = new Date(2000,1,1);
oDate.ToISO() = "20000101"


Date.ToDB

ToDB() allows the developer to get the current date and do a setfieldvalue without doing messy conversions.

Date.ToDB() //This returns the current date in MM/DD/YYYY format for setfieldvalue


Date.Compare
Compare() is a really powerful shorthand method of comparing dates or datetime.

A common business requirement is to ensure the currently selected date is greater than the created date, but less than a future date.

Heres how we would normally perform this operation.

//Convert to date object
oCreated = new Date("12/31/1999");
oFutureDate = new Date("1/1/2001");
oCurrentDate = new Date("1/1/2000");

If (oCurrentDate.GetTimeStamp() > oCreated.GetTimeStamp() && oCurrentDate.GetTimeStamp() < oFutureDate. GetTimeStamp ())


ABS does it in one line

Date.Compare("1/1/2000",">","12/31/1999","<","1/1/2001") = true


Heres a couple more examples of how it can be used to quickly compare dates.

//Created for date comparison of date1>date2 or date1>date2>date3
//Example 1:
Date.Compare("12/31/1999",">","1/1/2000") = false

//Example 2:
Date.Compare("12/31/1999","<","1/1/2000",">","") = true
//for the case of open date


Array.PSToStr

PSToStr () converts a Siebel PropertySet to a string for debugging. This is a very common situation for developers to find themselves in.

But it’s the implementation of this function as part of the Array object, which makes it unique. This allows it to be executed from Global scope, anywhere in the application, without using business service script libraries.


var oPS = TheApplication().NewPropertySet();

oPS.SetProperty(“A”,”1”);
[oPS].PSToStr(); //This returns a string representation of the PS


[Reducing code in your application]

Date.Compare() is a really good example of how prototypes can reduce code in your application. This prototype allows a developer to use date strings, to compare dates, without having to manually convert them to date objects.

Converting strings to dates is integral to comparing Dates correctly in Siebel, so instead of having these date conversion routines littered across the application in BCs, Applets and BSs, ABS prototypes this functionality to the Date Object.

ABS Prototypes is a feature purely for coders, but even if you don’t write a lot of script, whatever script you write will be very compact.

What if your project has massive amounts of scripting? We all know these projects exist.

Some projects start off with the noble principle of “exhausting” every declarative means of configuration, before turning to script, but this usually dosnt last, and there are a few common reasons for this.

    * Project cannot say “No” to funky ideas from business
    * Tight deadlines
    * In-experienced developers


Its likely to be a combination, if not all of the above. Its natural that people pick up scripting quicker than using WF, a junior can come in fresh from high school, know a little bit (or a lot) of Javascript, copy a bit of code from here and there, and with a small amount of effort, get a working solution.

Using prototype allows projects to build your own code library, these functions are bound to the standard ECMA objects, and can be re-used across the application without instantiation.

[Reduce memory usage]

I know you didn’t pay much attention to Siebel’s definition of prototype, but its interesting to revisit it (a part of it).

    Object prototypes are useful to be sure that every instance of an object use the same default values and that these instances conserve the amount of memory needed to run a script. Then every instance of the object use the same function instead of each using its own copy of it.


At this stage, we have a little more context of what prototype can do for our projects, and the Siebel definition seems to be more comprehensible.

But for the project managers, and executives out there, the prototype objects ensure that functions are instantiated once and shared across the application, and by taking advantage of prototypes, a project can reduce the memory usage in the application.

With a robust suite of prototypes at the core of your application, you have a more scalable and manageable solution at hand.

[Conclusion]

The ABS Prototype feature, dosnt make people better scripters, but it does reduce the amount of scripting in the application, and provides a repository of common routines, that in-experienced (and experienced) developers can rely on, without re-inventing the wheel.

Benefits of using Prototypes


    1) Reduce the size and clutter in the repository
    2) Reduce redundant code writing
    3) Standardize implementation of common routines
    4) Easier code maintenance
    5) Speed and streamline up code development
    6) Reduce memory usage


Pre-requisites


Prototypes should be implemented by developers with a solid understanding of ECMA script (not eScript). Improper implementation of prototypes can lead to memory leaks and defective behaviour across your application.

This also applies to projects that currently have ABS, and want to enhance the prototype library.

Projects need to ensure that there is a clear owner for the prototype library, and this person or group, have exclusive controls to these library functions, and makes changes on behalf of everyone. This ensures a layer of quality control, and a consistent coding standard is maintained for the project.

ABS Framework - Logging & Tracing Module

Log files are the bread and butter of every developer, so every once in a while it is interesting to meet a developer who has never used Trace() before. So how do these people troubleshoot Siebel? Using debugger, amazing!

Although debugging is useful, it’s not always reliable. In complex scenarios, when you have logic across different objects, the debugger just dies, or jumps around erratically. In these cases it’s just more efficient to dump out all the information to a file and analyse what went wrong.

From the most mundane, to the most critical problem, having informative logs is crucial to solving problems quickly.

For this purpose Siebel provides us with a basic tool.

    TheApplication().Trace()

Good old Trace, what this does is allow us to route key information to a log file during script execution. This same log file is used by the Siebel application for its application logging. So the first frustration developers get is all the information they are trying to dump out, is being buried by all the Siebel internal object allocation and destruction information.

Trace() is used by developers during the build phase and is inserted when a problem is found or in key areas for unit testing, and it is removed before the code is migrated into the test environments and ultimately in production.

Trace()
does the job, and gives developers the basic means to troubleshoot problems. Its function is not flashy, and it’s a little better than popping up an alert box, but we all learn to live with it pretty quickly.

[Paradigm Shift]


With that perspective, anyone that looks at ABS business code, will notice one major contrast to the above logging paradigm.

The ABS tracing module is used as part of the program design, rather than to troubleshoot problems as they arise.

In standard code, we normally trace the start, end and catch of each function, and put lots of comments to explain the code.

In ABS code, tracing is done at the start, end, catch, and is put at key decision points in the program, and this is left in the code, even when it is migrated into production.

The advantage of doing this is two fold.

1. The code is self documenting
    By including descriptions of the program logic in business speak, anyone can turn on tracing, perform the function, and the system will spool the program logic to a log for analysis.

2. On demand function execution information
    Since the tracing code is part of the program design, a developer can go into any environment, look at the ABS logs, or re-run the function, and have access to the details of the function execution details.

Similar to the way Workflow provides a debug mode for developers to see step and variable information of the runtime action. This ABS design feature closes the gap on the advantage that declarative configurations once had.

This is quite powerful, because it allows the developer to debug the problem live in an environment with real data, which can’t always be created on a local environment.

[Logging Levels]

Conforming to the Siebel logging standard, the ABS logging module has 5 levels of logging detail. Setting this value controls the amount of detail that is spooled to the log file. By default it is set to 3, but this can be overridden by the developer in the system preference or in the code.



[ABS Logging & Tracing components ]

    1. MSG object
    2. LOG object
    3. EXCEP object


[MSG Object]

One of the key design principles around the ABS System is re-use. Messages can be categorised and parameterised and re-used across the application.

To display errors or log error messages, we need to create our own message category in the Application, ABS encourages this over hard coding custom errors on the fly.

The ABS System creates a category called ABS Defined Messages.

Instead of using numbers and defined ranges for their use, the ABS Logging module uses identifiers with the following naming standard.



The ABS Defined Messages is only used for the ABS framework for standard error messages, to display more specific error messages, we need to create our own custom message category, and follow the above standard to define our messages.

Although it is not enforced, it is encouraged to follow this standard, because it makes managing error messages, and looking up their relationship to the functional areas easier.

[LOG Object]

This object defines how a function is logged, and does the actual job of tracing the messages to a file.

ABS Log files are generated in the following format, but can be changed according to individual user preferences.































 LOG object Methods
 Begin  Tell the logging module that a new function has begun
 Step  Used to record key milestones in the script and document the process
 StepResult  Used to document the result of a milestone
 End  Tell the the logging module that the function ended without any errors
 Error  Logs the error object



The basic construct must be built like this, for the proper logging and log format indenting to happen.



[EXCEP Object]


In a standard application, when an error is raised, the developer can choose to override this error, to provide a different message that is more suited to the context, or bubble it up the the parent function, but local variables are lost when the function loses scope.

In ABS, when an error occurs, the EXCEP object is thrown, the relevant parameters are captured and stored in the EXCEP object, and the original message is discarded after it is logged, the EXCEP object is then bubbled up in the function chain.

When the error bubbles back to the base function, the parameters are written out along with the error message.

This is very interesting, because it allows us to display a meaningful error message with full context of the parameters at the point when the error occurred.

[Example Error Log]



This is the function calling path from the above example.
    BO_Service -> LOV_Service -> LOV_GetValue -> LOV_GetAnyField -> BO_Query -> SYS_Assert

The error is raised at SYS_Assert, but it has no useful information at this point, so the error is thrown up the chain to BO_Query.

BO_Query is the real reason why the exception was raised, the arguments captured by this function are important, and will not be available once the function finishes, so it is bubbled up further along the function chain, with arguments captured from previous functions, until it reaches BO_Service

BO_Service is where the message is finally displayed. The cause of the error is due to a BC query that returned no results, but you want to override this, and display something more meaningful to the end user, but still log the actual technical reason for the developer.

The result is an informative message that contains details gathered from various parts of the function calling chain.

[Consolidated Server Logs]

The ABS Logging module solves a very fundamental problem with Siebel server logs. If you are in a multi-server environment and have 10 Siebel application servers, each will have its own set of application logs. So what happens when there is an error? We need to find out which server we were logged onto!

Why do we have to hunt for our logs?

ABS allows us to save logs from all our application servers in one central location.


Developers and environment guys a like, will really appreciate this feature. The design of ABS is an evolution of the way Siebel manages its logs.

[Self Documentation]

Traditional documentation and diagrams can be quickly outdated, especially if the rules are complex, and change every release. Script should be easy to read and understandable, the ABS system takes this idea further, and uses the logging objects to document the system.

With the correct usage of these functions, the ABS logging module will allow anyone to go into the system, and generate 100% accurate documentation of the system in business speak.

[Pro-active Error handling]

During the build and test phase, a developer builds a piece of functionality, does the unit testing, and migrates the code for testing. The tester will look at the build and raise defects that will event get re-assigned back to the developer. This process can take days.

The ABS system takes a more proactive approach, when ever an error is raised, it uses a SR style ticketing system, and assigns the error, based on its category to the correct position, in real time. This way a developer can get all the details of an exception, even before the tester has even realised there was an error.

[Conclusion]

The ABS logging & Tracing module provides the following features

    1. Detailed contextual error messages
    2. Step execution and function parameter information
    3. Self documentation mechanism
    4. Problem ticket assignment
    5. Consolidated server logs
    6. Works in WF and Script


Developers will appreciate the level of detail provided by the ABS system.

    1. Point of error
    2. Function calling path
    3. Function inputs and outputs
    4. Name, Value, and Type of arguments used in function

ABS can generate a lot of logs, so its important to keep your eye on disk space. The good news is the design of ABS allows all logs to be saved to one central place, so you only have to monitor one location, unfortunately, we cannot do the same for Siebel logs.

The developer shouldn't have to hunt around the logs for an error, then wonder where it exactly originated, and what were the conditions that caused it to error. All this information should be captured at the point of error.

If we reflect for a moment and compare the ABS logging module to the standard Siebel solution, the TheApplication().Trace() feels somehow inadequate, its like trying to fight fire with a water pistol.

The ABS logging and Tracing modules provides advanced tools for projects to quickly identify problems, turn around a solution and focus on the delivery.

What is the scope of a variable in eScript/Browser Script?

It is considered best practice, that we should always declare our variables outside the try/catch block. It is also one of the main recommendations of the following Siebel support document.

Assigning Null to Variables [ID 508828.1]

This was the question that was asked by the customer in the above article:

"In order for a variable to be referenced inside of a finally block, is it required for the variable to be declared before the try block, or can it be declared within the try block without any risk of not having all of the null statements work properly."


And Siebel provided this answer:

"If a variable is declared in the try block, there is no way to use them in the catch or even in the finally blocks, so using them in
these other blocks will lead to have an execution error."


This is the example that was provided to support this claim.

function foo()
{
var var1;

try
{
var var2;
if(true)
{
var var3;

for(var index = 0; index < 2; index++)
{
// Accessible variables are var1, var2, var3 and index
}
// Accessible variables are var1, var2 and var3
}
// Accessible variables are var1 and var2
}
catch(e)
{
var var4;
// Accessible variables are var1 and var4
}
finally
{
// Accessible variable is var1
}
}

This article was written by a very knowlegable person. The quality of his answers on Support web, shows that he has quite an extraordinary understanding of scripting, so one does not naturally question this sort of authority, but something didnt add up.

eScript which is based on ECMA script, does not have block level scoping. This is very important, because it means that the above test case will never prove true. Dont take it from me, take it from the ECMA standard itself, here is the reference.

http://www.ecma-international.org/publications/standards/ecma-262.htm

"A Block does not define a new execution scope. Only Program and Function Declaration produce a new scope"


There are two exceptions to this rule.

"the scope chain of the execution context is affected only by with statements and catch clauses."

But lets put standards and theory aside, because Siebel can add its own flavour into to the mix, so lets actually test the damn thing.

Take the above script, and trace out variable var2 in the finally block, this should not work according to the Siebel recommendation, but it does.

function foo()
{
try {
var var2=2;
}
catch(e){
}
finally {
// Accessible variable is var1
TheApplication().Trace(var2);
}
}

The explanation for this is, is eScript like ECMA Script has function scope. Any variable declared inside the function is a local variable, and is available throughout the lifetime of the function.

The test was done with primitive and complex objects, and has been tested in IE 6 Javascript, Siebel 8.1.1.1 eScript ST Engine, and Siebel 7.8 T Engine.

This illustration does not invalidate the Siebel recommendation, but it does highlight the importance of understanding why we have to do things in a particular way, and what effect it has.

Declaring variables outside the try/catch blocks comes from solid tradition, behind programming languages such Java and C. And if you are starting out in ECMA Script and want to learn Java in future, then this is one less scripting habit you have to change.

The only caution i would give, is dont add complex initialization routines for your variables outside the try catch, because you do not have the safety if it fails. Initialize it before the try, and use it in the try/catch/finally body.

Results of ImposSiebel Toolbar poll



The results are surprising, and shows that readers are heavily divided on two features.

The winner of course is the field/column/table information, users who voted for this option are practical, they want fast access to their configuration without messing about in Tools.

What is surprising to me, is the number of people who voted on Browser Script tracing. It might just be my reader demographics, because on most projects, Browser Script is avoided, and given in for Server script solutions.

Although its use should be minimized, its fair to say that Browser Script functionality offers really cool functionality for end users, that cannot be achieved using Server script. People who voted for this, are likely to be flashy, and sacrifice practicality for a little luxury.

I have prototyped both features, but can only focus on one, because both require a lot of work (my spare time).

But as a consolation prize for the code junkies out there, i'll dedicate a couple of articles on some obscure Browser Script behaviour and tips for rapid development.

The new feature will be available in a few weeks (maybe less), so keep an eye on ImposSiebel twitter for updates on the next IS Toolbar version.