eScript: The Siebel Stack

Does your Error Handling framework provide you with a stack trace? People have asked me whether its possible to get the stack trace, or get the name of the function when an error occurs in Siebel. I cautiously say Yes to both, because this method can be easily abused. This article is aimed at the framework designer looking to enhance their project's error handling capabilities.

Respected ex Siebel engineer Mike M Lin, wrote an article on Getting the Call Stack from eScript. In that article, he raises a Siebel exception, and scrapes the error message property to get the call stack. Unfortunately in Siebel 8, Siebel has removed the stack trace information from the error message property when using TheApplication().RaiseErrorText. Siebel has also blocked the ability to enumerate the error object, so the same test case can’t be performed.

According to bookshelf, when an operation fails, Siebel generates an Exception Object. The exception is documented with two properties: errCode, and errText

I’ve taken the Siebel example, added some log statements, and put it through The Harness



We verify that the error is indeed an instance of the Exception Object, and that the Siebel example works.

Next I modify the example to include the two properties that Mike M Lin, identified as part of his test case:

name, message.



Name turns up a blank, and message stores the same value as errText. There is no stack trace in sight, so I try the same test case with TheApplication().RaiseErrorText(), as Mike did, but unfortunately this also produces no stack trace.




Producing the Stack Trace

We can conclude that the Siebel Exception object no longer produces a stack trace, but Siebel Exception objects aren’t the only types of Error objects that are created in eScript. According to the ECMA specifications, which Siebel eScript is based on, there are other types of errors that can be thrown.



In the above example I’ve created a Reference Error, which reveals that the Stack trace is accessible with other error objects within Siebel.



Heres another example, showing the stack trace that is produced with more than 1 function. You'll notice that the stack trace at this point contains a dummy error message, but we'll see how this can be utilised a little later.



Getting The Current Function Name

Getting the stack trace is nice, but it would be great, if we could also get the name of the function that the error occurred in. We can see from the above stack trace, that it would be trivial to write a routine to extract the name of the last function.

The stack trace format is different of the Siebel 7 example, but it's not hard to parse. Heres a quick test case that I put together.



Note: In Siebel 7, the name of the current function can be accessed by "arguments.callee" in eScript, however this has been deprecated in Siebel 8.

Error Object On Steroids

Armed with the above knowledge we can now produce a stack trace at will (even for Siebel generated exceptions), throw back a custom error object containing our stack trace, and log it as part of an Error handling framework.

The concept of throwing a custom error object has been discussed before in ABS Framework - Logging & Tracing Module. The author of the ABS framework has provided some really interesting concepts around error handling, but if we strip away the message lookups, variable bindings, and the bells and whistles, we can take away the concept of throwing custom error objects, and mix it with our idea of generating a custom stack trace, plus extracting the name of the error function.

It can be boiled down to the following steps.

1. Throw an error
2. Check that the error is not an instance of our custom error
3. Cause a stack trace using the method described above
4. Scrape the relevant stack trace information, and ignore the dummy error message
5. Scrape the error function name from the stack trace, also described above
6. Create an instance of custom error with the above data
7. Insert the original error from the real error object into the custom error object
8. Re-throw the custom error
9. At your root function check for the custom error, and log the stack trace, error information


The above steps outline how to create and handle a custom error object. A framework designer can take ownership of it, and incorporate these ideas into your own in-house error handling framework.

Logger Concept

Another complimentary method is to implement a custom script logger. This was also introduced to readers, when we visited the ABS framework logging capability. For a real life example of a logger, Siebel master Mik has kindly shared his design here.

A sample logger template looks like this.


function MyFunction (){
try{
     log.begin("MyFunction");//hard coded function name
}catch(e){
     log.error(e);
}finally{
     log.end();}
}


Every function would contain the above template, in which a custom logger is called with 3 main methods.

log.begin - Pushes a string of the current function name onto a custom stack
log.end - Pops the last function from the stack.
log.error - Logs the error

When an error occurs, you know that the last function in the stack is where the error occurred, and by its very nature, the custom stack can be simply printed out, as it is just an ordinary array.

The downsides of this technique against the one described above is that it does not provide line numbers, and the developer is also responsible for hard coding the correct function name in log.begin, and also consistently calling log.end.

Conclusion

By causing Siebel to stack itself, we are able to take advantage of the extra information that is provided by the standard ECMA error objects. This provides crucial information of the events leading up to any Exception, including the exact line where it occurred. And with a little added imagination, we can collect further information from each function as the error object is bubbled up the chain, a la ABS framework.

In this article, I've shown how we can get the name of the current function, generate a stack trace at will, and its importance in error handling. Integrating it into your own framework is the fun part, this will require engagement with your core framework professionals, and will require an impact analysis.

Credits goes out to Mike M. Lin for providing the seeds for this article, Mik Branchaud for sharing his logger design, and Mr ABS for sharing his wisdom on error handling in the ABS framework.



Reactions:

5 comments:

  1. Excellent Article.
    Can you elaborate further on the following point "Armed with the above knowledge we can now produce a stack trace at will (even for Siebel generated exceptions), throw back a custom error object containing our stack trace, and log it as part of an Error handling framework. "

    i.e. how to force a stack trace on a defined Siebel Exception

    ReplyDelete
  2. see snippet code below

    function MyFunction (){
    try{
    TheApplication().RaiseErrorText("Error message");
    }catch(e){
    if(!instanceof MyCustomError){
    e=getStackTrace(e);
    }
    throw e;
    }finally{
    }
    function getStackTrace(e){
    //See 'Producing the Stack Trace' in the article above
    //return custom object
    }

    ReplyDelete
  3. can siebel work with imacros to automate siebel navigation?

    ReplyDelete
  4. How would you have the Server Script reference and pop up a window (not a popup applet) from a button? I'm just learning siebel and trying to get the hang of the scripting. Bookshelf is of little help on this matter, so I feel.

    ReplyDelete
  5. Hi,

    eScript is executed on the server, so it would not be suitable for this requirement. If you want to open up a browser window on the clients machine, it is better done using browser script or symbolic urls

    ReplyDelete

Comments are open to all, please make it constructive.