Siebel 8 Tab Order defect on Popup applets (8.1.1.1)

We seem to have lots of encounters with Popup applets here at Impossible Siebel

About Record Applet Challenge

Siebel 7 Dual Screen popup

Siebel 8 Dual Screen popup

Conditional Popup based on button click

MVG Popup Challenge

[Another popup challenge]

On the last day before code freeze, the following challenge came through as a critical defect.

The problem in Siebel 8, is that the tab order is ignored on all popup form applets using grid layout (CSSFramePopup).

The tab order still functions correctly in view applets, but on popup form applets, the tab always moves in a sideways fashion, from left to right, no matter how the sequence property is set on the controls.

This may not seem like a huge issue, but for a customer facing staff this can be mission critical. The tab order allows staff to efficiently key in data in a logical sequence, without using the mouse, and if the tab order changes all of a sudden, they have to un-train their old typing habits and adapt to the new behaviour.

This problem was escalated to the Siebel engineers and we were advised that there is no workaround for this behaviour.

This is bad news, especially for customers who have upgraded from 7.8 to find this functionality has been broken.

[Tab Behaviour]

To fix the root cause of this problem, we need to understand how the tab behaviour works.

Is it controlled by class/ActiveX code? or by HTML? or by Javascript/browser script? who knows?

The answer is HTML. The actual solution will lead us to a very obscure part of the application.

When we configure Tab order in Siebel, we need to set the HTML sequence for the control on the applet or use the format menu option. The latter option is disabled in Siebel 8.

When siebel generates the HTML for this control definition, it creates a tag called tabIndex which controls the tab sequence in the browser.

Take a look at the following example, and copy it into a plain text file and run it to see how it works.

<html>
<head>
 <title>Controlling TAB Order</title>
</head>
<body>
<SPAN>
 <form>
   <table border=1><tr><td ><div class=GridBorder>
   Field 1 (first tab selection):
   <input type="text" name="field1" tabindex=1 /><br />

   Field 2 (third tab selection):
   <input type="text" name="field2" tabindex=3 /><br />

   Field 3 (second tab selection):
   <input type="text" name="field3" tabindex=2 /><br> </div></td>
     </tr>
     </table>
 </form>
 </SPAN>
</body>
</html>


The problem is, this particular tag, cannot be inspected by looking at the HTML source, or sniffing the HTML, because the HTML source is the pre rendered content, which contains all the HTML code and Javascript commands that your browser interprets on the fly to create the actual content that you see.

The only way to get at this information is to traverse the DOM tree, and spool out the post rendered structure (which is the true representation of what you seen on the screen).

When i spooled out the HTML that Siebel rendered, the controls were missing the tabIndex, and it was also malformed.

No wonder it didnt work!, this tag was correctly rendered for applets in the view frame, but was not for popup applets.

[The challenge]

Our particular requirement for this challenge, was to only fix one applet, there were a few others which were affected, but given where we were, the business accepted this compromise, because there was likely to be a lot of hard coding.

We need some mechanism to control the tabIndex, i could query the repository to get the control sequence, but it wouldn't be easy to grab this information from Browser script and was overkill in every sense of the word, the alternative, was to hard code the tabIndex references to correspond to the HTML sequence of the actual control on the applet. Not very nice, but it was an idea.

[The solution]

An unexpected treasure appeared, when the post rendered Siebel HTML source was analysed, the malformed tag actually contained the HTML sequence, but it was disguised by an empty identifier and was actually hacked to the back of another attribute. It seemed that Siebel did generate the sequence attribute, but chopped off the tabIndex indentifier required for this to work.



So now that we have the most important ingredient (the tab sequence of all the controls), we can modify the HTML to create the tabIndex property and inject our sequence.

Its easy to access a node, and grab its attribute, but its difficult if the attribute dosnt have a name, so how do you reference some thing that has no reference? It took me a while to figure out, but heres how i restored the Siebel Tab order.

Put the following code on applet load:
var oControl = this.FindActiveXControl("Any Control Name");
var oObject = oControl.document.body.getElementsByTagName("object");
for (var i=0; i < oObject.length; i++)
    oObject[i].tabIndex = oObject[i][""];


What this does, is grab a hold of any arbitary control to gain access to the DOM. We then use this handle to go to the top of the DOM hierarchy, and grab all the tags for the applet controls, and insert a tabIndex attribute, and assign it the value of the un-named identifier.



The final solution involved no hard coding of the sequence or control arrays, nor did it require a server trip to retrieve this information from the respository. So we ended up fixing all the other applets that the business wanted.

This is only meant to be a stop gap solution, and hopefully Siebel will fix the bug soon. Dont hold your breath, but also dont go crazy and put this on every popup applet in the application. This solution is only designed for HI mode and was tested on 8.1.1.1, a SI fix wasnt applicable, and wasnt explored. (Thanks to KW for help on analysing this problem)

ImposSiebel Toolbar, About Label

I had a conversation with some Siebel architects not too long ago, and we were talking about Siebel 6. One of the best things about the interface (probably the only thing that was good), was the fact that, when you hovered over any label on the client, it would reveal the actual BC field name in the application status bar.



This was a golden nugget for developers, because instead of going to the applet, viewing the layout, inspecting the control, scrolling down the properties window to get the field name. Siebel 6 provided this information plainly to anyone who cared to look.

The person who designed this functionality was obviously an engineer, and the person who killed the feature in Siebel 7.0 was most likely a marketing person. Siebel professionals who came from the 10 year batch, will remember this feature, and will be happy to know that i've brought this feature back.

This feature is provided for pure nostalgia, but will not have any practical value anymore and I'll explain why soon.

[About Label]

Rather than borrow design cues from a 10 year old interface, i've come up with something a little more modern.

'About Label' provides the developer with detailed information about the label of any form applet inside a floating window, which can be interacted with to show low level BC information.

To invoke this feature, goto any form applet, and pay attention to the labels. When you hover over a suitable label, the background of the label will change color, indicating that this feature is enabled.



Double click on the desired label to call 'About Label'. A dialog will appear showing the following summary information about the field, if it is available.



Calculated fields will not have mapped columns, VBC fields will not have a Table, and System fields will have no definition.

So depending on the kind of field you are inspecting, the following information is displayed.

1. Field Name
2. Column
3. Calculated Value
4. MVL Name
5. Dest Field
6. Dest BC Name
7. Picklist Name
8. Picklist Type Value
9. Table Name

Click on the toggle icon, and the dialog will expand to show the entire list of configured properties for the field.



And finally the field name will be displayed in the status bar for those Siebel 6 hippies who want to do some reminiscing. Give me a Hi-5 in the comments, if you're a hippie.

[Limitations]

1. List applet support
This feature is sorely missing, but it is a tough one, and requires an overhaul of the current design to work, so dont expect it on your radar anytime soon.

2. Popup applet support
This also requires some new design to work, but consider it a weak bleep on your radar.

3. Home pages/SI mode support
SI support is possible with a little tweak and some further testing, but hasnt been enabled. Consider this one a phantom bleep that might appear anytime soon.

4. MVF Column/Table name
'About Label' doesnt show the mapped column/table name for MVF fields. This is a personal annoyance for me, but i dont have a quick solution, so this will be a future enhancement.

[Whats on the horizon?]

Theres still a few features of "Super About View" that i have yet to port over to the ImposSiebel toolbar. The most notable are listed below.

1. About Script

Displays all browser and server script related to the current BC and Applet in an explorer tree. This is useful to inspect the behaviour behind a button, or action on the UI, without going into Tools.

2. About Applet & About BC

Displays low level details about the user properties, and object properties of the Applet and BCs. This is useful to see why fields are read only, or what user properties could contribute to the UI behaviour.

3. 40 second Repository Search

As the feature title suggests, the Impossible Siebel toolbar can scan the repository in roughly 40 seconds, and display a detailed report on the repository reference to any string, field, applet or view definition. Try this with a standard Siebel full repository search, and you'll hang your tools for a few hours!

This will be the last major release for this year, and mostly likely the early part of next year. I must admit, i skipped some corners to get this release out in time, and also deliver the ABS articles. So i will focus on refactoring the code, and creating object wrappers, so its more scalable for future enhancements.

Although this is mostly under the hood enhancements, the foundations will make the above enhancements easier. But to keep you guys/gals happy, i'll provides some nice easter eggs along the way so you dont get bored with all this stability, and scalability nonsense.

ImposSiebel Toolbar, Version 0.54 Release Information

This is the anticipated version of the Impossible Siebel Toolbar, with the "About Label" feature, which was the winner of our last poll.



"About Label" should be fairly obvious to use (hint, its has something to do with Labels). If you can't figure it out, a follow up article will be posted soon to explain how "About Label" works.

Before you skim over this article, the new XML configuration file is mandatory for the "SQL Profiling", and "About Label" to work. This is required for new and existing users.

[Installation]

1. Existing Users


Managed Option
Under the ImposSiebel Toolbar options, just click on "Refresh
Toolbar"

Bookmark Option
If you are using the server copy, i've already uploaded the new
version.

2. New Users

Follow the instructions in the first article
http://www.impossiblesiebel.com/2009/09/impossiebel-toolbar-beta.html

[XML configuration file]


This new component is critical for "About Label" and other future
functionality to work.

Create a XML file called "ISConfig.xml" with the following contents and put it in the following directory.

C:\Program Files\Impossible_Siebel\
<IS>
       <odbc>
              <source>
                     <dsn>Your Local Siebel DSN</dsn>
                     <username>datasource username</username>
                     <password>datasource password</password>
              </source>
       </odbc>
       <sqlspoolfile>c:\spool.sql</sqlspoolfile>
</IS>

This directory will already be there for users who have opted for the "Managed" version.

[New Features]

1. About Label
This feature provides the developer with detailed information about the label of any form applet.

Keep an eye out for the next article, and i'll provide a tutorial on how to use this functionality.

2. Current Applet and Id
Next to the [IS Menu], i've added dynamic information on the current active applet, and the current Row Id.

When you hover over this text, it will be copied to your clipboard automatically. This is useful, when you have a popup window and want to know its name.

3. Position sensitive "About View", "About Label"
The most annoying behaviour of the previous version, was "About View" only appears in a hard coded position near the top. So if you have a long screen, and try to invoke "About View", you wont see it until you scroll up.

"About View" is now position sensitive to where you double click. This enhancement also applys to "About Label", however other dialogs are still hardcoded.


[Changes]

1. Invoking "About View"

In the previous version, "About View" was invoked by double clicking on any free space in the main view. The term "main view" dosnt really mean anything to anyone except me.

So i've made it more user friendly, by allowing the user to double click on any free space in the application, and this will bring up "About View"

2. Active position/Login information
This information has been shifted from the right of the toolbar to the left

3. SQL Profiler Total Operations

SQL Profiler shows the top 10 operations ordered by SQL cost. There are some cases where you could get thousands of small transactions taking a large amount of resources. In this case the top 10 operations wont reveal the whole picture.

I've added the Total number of SQL operations, so if you have a nasty piece of rescursive SQL, this new information will reveal the proper context of the top 10.


[Fixes]


"About View" Smart Script Crash

Fixed an issue that caused the toolbar to die under a smart scripts
view.



[Known issues]


Cannot establish connection to local database
In Siebel 8, if you are connecting to an encrypted local database, you need to have Tools open at the same time.

You need to open Tools and re-start the client for the changes to take effect.

Server DSN issues
A server DSN can be configured, but it is not recommended because it can be slow. Also the toolbar has only been tested on DB2, and therefore is not guaranteed to work with any other DB vendor.

SI About Label
"About Label" has not been implemented in SI.

ABS Framework - Business Object Library

The ABS Business Object library is probably the most important feature of ABS, from a benefits realization point of view, and heres why.

ABS can make your project atleast 2x more efficient.

The ABS framework provides a global class of functions that allows developers to write code that is leaner, faster, use less memory and require less time and resources than traditional build methods.

That’s a really big promise, and we should be sceptical when someone makes a claim like that, but in this article I’ll look at how ABS achieves this, and how it can be quantified.

[Abstraction Layer]

The goal of the ABS Business Object library is to build on top of the existing Siebel BO functions, and provide the developer with tools to achieve complex functionality with just a few lines of code.

It’s difficult to talk about abstract concepts, without an example, so heres a scenario that all developers can relate to.

If you wanted to query an Account and get back the primary Address related to this account and return the state and city in an array, how many lines of code would it take?

Here’s the traditional way of writing this logic in standard Siebel eScript.

function GetAccountInfo() {
var aAddressInfo = [];

var oBO_Account = TheApplication().GetBusObject("Account");//1
var oBC_Account = oBO_Account.GetBusComp("Account");//2
var oBC_Address;//3

try {
oBC_Account.ClearToQuery();//4
oBC_Account.SetViewMode(AllView);//5
oBC_Account.ActivateField("City");//6
oBC_Account.ActivateField("State");//7
oBC_Account.SetSearchSpec("Id","1-ABC");//8
oBC_Account.ExecuteQuery(ForwardOnly);//9

if (oBC_Account.FirstRecord()) {//10
oBC_Address = oBO_Account.GetMVGBusComp("Address");//11

if (oBC_Address.FirstRecord()) {//12
aAddressInfo[0] = oBC_Address.GetFieldValue("City");//13
aAddressInfo[1] = oBC_Address.GetFieldValue("State");//14
} //15
}
else {
throw "No Address found in the Account";
}

}
}
catch(e) {
throw (e);
}
finally {
}

return aAddressInfo;
}


That’s over 15 lines of actual logic, not including line spacing, and error handling. So how many lines does it take using the ABS BO Library? Just one.

Here’s how we would write the same logic using ABS.

function GetAccountInfo() {
var bErrRaised=false,aAddressInfo;

try {

aAddressInfo = TheAccount.GetChildFieldValueWithId(“1-ABC”,TheAccount.oBCChild_Address,["City","State"],true))[0];//1

}
catch(e)
throw (e);
}
finally {
if (!bErrRaised) return aAddressInfo;
}
}

Let me explain what is happening here.



















 Legend
TheAccount  This is a predefined ABS BO object that is always available in the Application.

Take it for granted that this exists, and you can use it anywhere, and in the chapter on the ABS Universal Object, I’ll explain how this object comes into existence.
TheAccount.oBCChild_Address  This is another predefined ABS BO object.
GetChildFieldValueWithId  This is a method of the ABS BO Object, which is inherited by all BO instances such as TheAccount. It allows the developer to query a child BC using a row id as a search spec, and return a set of values as an array.


[Inputs]



sId = Row Id

hbChildHandler: Child BC instance

hbChildField: Fields to return

bRaiseErrIfNoRecChild: throw error if not found

sSortSpecChild: Child BC Sort Spec


[Re-Use]

The above example highlights one of the main principles around ABS: Re-use.

Why do we have to write

GetBusObject(), GetBusComp(), ClearToQuery(), ActivateFields(), SetViewMode(), SetSearchExpr(),ExecuteQuery(),FirstRecord()

in every function, in every business component, applet or business service in the application, hundreds of time, over and over again?

We can start to imagine how this kind of code writing can lead to application bloat, adding to application maintenance, reducing the upgradability of a project, and obscuring business logic with un-necessary repetition of technical artifacts.

ABS encapsulates the above logic in a single function, that can be used anywhere in the application.

Writing less code, will definitely add to your efficiency.

[Upgradability]

One of the main arguments for using declarative configuration methods is that it can be easily upgraded. The reasoning is that if all your logic is configured rather than scripted, then the upgrade would be painless and carefree.

Well, that is really not the case. In 7.5 you could have WFs that have steps that were free standing with no connecting lines, 7.5 also allowed WF designers to have multiple start points. This is illegal in 7.7 onwards, and during the upgrade you will have to fix all your WFs.

Experienced people will see that WFs are not foolproof in upgrades, they are just as likely to be obsolete as scripted solutions.

The argument against using traditional eScript, is when you perform an upgrade, Siebel does not touch your script, so every piece of code has to be retested.

How does ABS differ?

The highly modular design of ABS makes it more favourable to upgrades.

For example.

If Siebel decided to make ActivateFields deprecated, and forced developers to use ActivateMultipleFields instead.

You’ll only need to find that one place in the ABS framework, and replace it with the new method. Of course, the unit testing has to be thorough, but once it has been unit tested in this function, the entire application will benefit.

Upgrades can never done by the push of a button, but if you given the choice of upgrading an application with a hoarde of WFs with hundreds of individually defined steps, a massively scripted spaghetti system, or a highly modular but concise scripted system, which one would you choose?

[Improve Efficiency]

Let’s revisit that promise again.

“ABS can make your project atleast 2x more efficient.

…write code that is leaner, faster, use less memory and require less time and resources than traditional build methods. “


Write faster code

If we had two developers with EQUAL knowledge and experience, 1 is skilled in eScript and the other is skilled in ABS.

Which developer would have the advantage? I think the answer is obvious. The eScript developer would have to write 15 times more code than the ABS developer.

That is an unholy advantage. Not only would the ABS developer be faster, but would also have 15x less code to troubleshoot if there was something wrong.

Leaner code

15 lines vs 1 line, need I say more?

The code is not only leaner, but also more representative of the business logic and more readable at the same time.

Use less memory

Business Objects and Business Components are only ever instantiated once, and re-used throughout the lifetime of the user session. This will be explained in more detail in a section for the ABS Universal Object.

Less time/resources

The tangible benefit that the ABS BO library brings to projects is obvious. To run and maintain a large scale project will require less time and resources. This puts project managers in a better bargaining position.

Theoretically, you would have to hire 15 eScript developers to do the same amount of work of 1 master ABS developer.

But realistically, you do not need to hire master ABS developers, you only need to get Siebel developers who have a solid foundation in scripting (preferably ECMA), and who are open minded to the ABS philosophy.

While you cannot hire just anyone that walks in from the street, you’ll only need a few very good people, rather than a brigade of good people.

[Conclusion]

The use of ABS is not widespread, and part of the reason for this is that it needs to be implemented as a total solution, and not in bits and pieces. And the most suitable implementations are the green field projects, or projects which are still young.

Currently there is only one Systems Integrator that is implementing ABS solutions on a grand scale, and the benchmark hasn’t been made public.

A 2x improvement in efficiency sounds controversial, but if we base our conclusion of other ECMA script frameworks, such as jQuery, Scriptaculous and Prototype. We know that scripting frameworks do deliver on efficiency, as well as improving code readability, and application maintenance.

We saw that by using ABS, build and testing times were cut by a factor of 15. Saying that ABS delivers 2x more efficiency is quite conservative, but keeps it realistic.

Code bloat is detrimental to the long term maintenance of the application, and the main culprit is eScript, so its interesting to see a framework like ABS tackle this problem head on with a very radical tactic:

Using ECMA Script to reduce eScript.

Implementing a concise, highly modular, Siebel framework, using ECMA script to lay the foundation, is not something that your average scripting expert can achieve.

People that can pull off this sort of feat, are your architect of architects.

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.

Understanding the scope of "this" in Browser script

Due to the un-holy interest in the browser script tracing feature of the ImposSiebel Toolbar poll, this article is a little treat for all the closet Browser Script fans out there.

The behaviour described below is fundamental to ECMA script, but will catch most Siebel professionals off guard, and theres a very good reason for this.

Lets start with an example to set the scene. This scenario is lifted from the following Article on the Siebel Support Website, and summarised below.

[Goal]
How Can You Use Browser Script in Siebel 7 onwards to Set Focus on a Different Applet or Control? [ID 477070.1]

[Solution]
1. Query for the applet that you want to receive focus. Add the following to the (general) (declarations) section of the browser script:

setTimeout("DoSetFocus()",1000);


2. Create the following function

function DoSetFocus()
{
var appFocus = theApplication().FindApplet("Account Entry Applet");
var objControl = appFocus.FindActiveXControl("MainPhoneNumber");
if (objControl.canHaveHTML == false) {
objControl.focus();
} else {
objFocus = objControl.getElementsByTagName("Input");
objFocus = objFocus[0];
objFocus.focus();
}
}

Since there is no error handling provided by the Siebel examples, we'll add some of our own.

1. We'll modify the solution a little, and put the setTimeOut in the Applet load section.


function Applet_Load ()
{
try {
setTimeout("DoSetFocus()",1000);
} catch(e) {
//handle error here
alert( e.toString() );
}
finally {
}
}


2. And here is the set focus function with a try/catch, but instead of hard coding the applet name, we'll just use this.Name().


function DoSetFocus()
{
try {
var appFocus = theApplication().FindApplet( this.Name() );
var objControl =
appFocus.FindActiveXControl("MainPhoneNumber");//change this to a valid
control

if (objControl.canHaveHTML == false) {
objControl.focus();
} else {
objFocus = objControl.getElementsByTagName("Input");
objFocus = objFocus[0];
objFocus.focus();
}

} catch(e) {
//bubble the error back up the chain to be handled
throw ( " > DoSetFocus > "+ e.toString() );
} finally {
}
}


3. Compile and run it.

If you've tried it, you will notice that all it does, is generate an IE javascript error.

We expect this code to get into DoSetFocus, and set focus to our desired field, and if there is any error, it should throw an error back to the caller, which will be handled by the alert() in Applet_Load.

So can anyone see anything wrong with this code?
There are actually two fundamental flaws.

To prevent any spoilers, do not scroll down any further, scroll back up now....




























If you've gotten this far accidentally, and wondered ...WHAT THE HECK WAS THAT? That is "Modern Talking", the best of 80s music from Europe.

This will bring back some good memories for GenX europeans, but for our majority US readers, i apologize, because sadly, Pop synth never caught on in the US, Australia or the UK, but in Europe and Asia this band was as big as the Beattles.

"You're my heart, you're my soul" was a master piece from this classic german duo.

If you are still following this genre, Thomas Anders "Good Karma (2009)", has that classic Modern Talking sound that is so hard to find now days.



And for good measure, you cannot mention MT without Sandra Cretu. Again for our US readers, MT and Sandra's success can be closely paralleled to MJ and Madonna in the states. If i could only pick one Sandra song, it would be "Maria Magdalena", this is quintisential 80s pop synth, and unmistakable euro disco.

This is your last chance, if you dont want to be spoiled, go back now, but if you've endured through that, it means you really want to know the answer by now...

Okay, have you had enough of 80s German pop bands? Here is the answer

[Issue 1]
the throw from DoSetFocus() is not caught


This should be self explanitory, the root of the function is no longer Applet_Load, so when we try to throw the error, there is no one there to
catch it.

The setTimeOut function causes the scope to change, and DoSetFocus becomes the root calling function. With that in mind, we just need to change the throw to an alert to handle the error.


[Issue 2]
this.Name() is out of scope


this.Name() will return the name of the current Applet inside the vanilla
applet events (listed below)

Applet_PreInvokeMethod
Applet_InvokeMethod
Applet_ChangeRecord
Applet_ChangeFieldValue
Applet_Load

But when it is used in a custom function or the declarations section, the behaviour is different.

[So what does 'this' refer to?]

'this' can refer to the parent or current object depending on the current context.

In the case above, under the vanilla events, 'this' refers to the current applet, but inside a custom function 'this' actually refers to the view frame.

This isnt a bug, and the behaviour is expected, if we understand how these functions are created or instantiated by Siebel. The exact mechanism behind this behaviour deserves another article, but for now just keep this behaviour in mind when designing your functionality.

If you want to reference the current applet, in our custom functions, the workaround is quite simple, just use a global pointer to the current object.

Under your (declarations) section put this code


var that = this;


Now, we can reference the current applet correctly in every function, by using that.Name()

After writing this article, i found this document on Siebel Support

What Is the Scope of the "this" Object in Browser Script? (Doc ID477659.1).

This article documents this behaviour just as i have, spooky!

There is an important point worth taking from this Siebel article. Any code that is written in the declarations of an applet, is shared among all the other applets in the same view.

This is because the code that is written in the declarations section is part of the view frame, and since all the applets are part of the same container, all the variables will be shared.

Let me put together a diagram, so we can see it visually...Here it is.



It just occured to me, this diagram reveals something i never thought about before, are you guys thinking what i'm thinking? This really belongs in the next article.

But to conclude this topic, there is something about Siebel (Doc ID 477659.1) that i would like to add. In this arcticle it states...


"In server script:

The this or Me object is the object whose script you are editing at the moment.".


What its saying is, if you are on a BC, this.Name(), will always return the name of the BC no matter which function you call it from, likewise for applets, and business services, this.Name() will return the name of the object you are in.

The author who wrote this support web document, had Siebel professionals in mind, and while this is true in most cases, it is not not entirely accurate.

In the continuation of this article, i'll show you an exception to this rule, and the reason for this, is the same reason why the scope is different in Browser script.

ImposSiebel Toolbar, UI Search Spec

In this article, we'll use the IS Toolbar to reveal the following information

1. Find hidden search specs
2. Find the BC field name without going into tools

Hidden Search Spec

The UI Search Spec feature is quite un-assuming, but it deserves some attention, because it can come in handy when trouble shooting problems.

When talking about search specs, people immediately think of Applet or BC search specs. These are a couple of objects in tools where we can configure hard search specs in the application.

We can also set search specs in script, but this can be dynamic and is harder to tell if the search spec is applied or not. Damn those crazy scripters for making our lives more complicated.

The same thing happens when we go to a view with a PDQ applied. The PDQ applies a runtime filter on top of the BC and Applet search specs.

The UI Search Spec feature dosnt (yet) pin point where these conditional search specs are hidden, but it does reveal if theres a hidden search spec applied.

The UI search spec feature will reveal any runtime search specs, and allows the user to see what is not obvious.

Instructions

1. Goto any view with a PDQ, or where you know there is script that sets a search spec, such as in the PreQuery event, or simply execute a UI query (this will set a UI search spec)

2. Double click on any Applet title bar to bring up About view

You should see the About View dialog, with the UI search spec information.


Find BC Field Name

By the very nature of UI Search Specs, we can also reveal the BC field name behind applet field labels.

Instructions

1. Goto any applet and find a field to investigate

2. Click on the Siebel Query button, and type in "AAA" in that field.

3. Execute the Query

Now, double click on the Applet title bar to bring up About View again, and you will see the BC field name for that label in the UI Search Spec.

I tried this on the First Name control label on an Activities applet and got the following information.



And we can see that the actual field name is [Act First Name].

Its simple and time saving but to be honest its kind of a hack, but i have a much more elegant solution in mind. This is on the horizon, so keep your eyes peeled for this feature.

For the record, here is the list of places in the application where you can set search specs.

Applet SearchSpec
BC SearchSpec
Picklist SearchSpec
Link SearchSpec
Script SetSearchSpec
Script SetSearchExpr
Script SetNamedSearch
WF Siebel Operation SearchSpec
Report SearchSpec
Task SearchSpec

Theres also the implicit search spec on Drilldowns, which catches some people off guard, because you do not actually set a search spec, but it is implied when you set the source id.

ImposSiebel Toolbar, SQL Profiling

How many of us actually care about SQL performance? Mostly, only Solution Designers, but its important that we *all* consider how much impact our config has on the system.

Have you ever clicked on a button and waited a good 30 seconds before the system comes back? If yes, then this article is for you.

There could be a number of factors contributing to performance issues, but i'm going to focus on SQL performance.

Siebel produces a spool file for us to analyse, which is really useful, but only a speed reading SQL geek would be able to correlate the SQL generated with the Application usage and add up the SQL cost in their head on the fly.

For the rest of us, we have the ImposSiebel SQL profiling feature.

This feature brings SQL profiling to the masses. The idea is, that any junior should be able to use this to identify parts of the config that is taxing the system, and suggest ways of improving performance.

Before you start, make sure you are running a thick client connection, and have specified a spool file. This can be done, by adding " /s c:\spool.sql" to your Siebel Client shortcut.

Scenario
Identify a part of your application that takes a long time to respond.

It could be a button, or navigating to a certain view, or triggering a bunch of scripts, or generating some data.

Find it, but dont touch it.

Profile it!
I assume at this point, you already have the ImposSiebel toolbar running.

Now click the SQL profile icon, its that funny looking icon, which looks like two cyclinders behind a refresh icon. It should be next to the IS menu.


This starts the profiling feature. The first time you click this, it will prompt you for the location of your SQL spool file. The default is c:\spool.sql, just accept this if you've followed the instructions above or enter your own file location.


If you want to specify another file, this can be accessed by the following menu option.


Now engage your performance hogging function, and wait until it has finished.

Click that SQL profiling icon again to toggle it off. We are now ready to analyse the SQL.


You should be presented with the following dialog.


This shows you the total SQL cost of your function, and also displays the top 10 SQL ordered descending by Cost, along with the corresponding line numbers in the spool file.

When a button is taking 30 seconds to return control, its usually caused by 1 or 2 bad SQLs, with this tool, we can instantly identify the culprit, and focus our efforts in reducing this cost.

Click on the cost for the desired result, and the offending SQL will be shown to you.


Now, unless that speed reading geek has photographic memory as well, i think we have the competitive advantage here, and have just saved ourselves atleast 30 minutes, swimming around neck deep in SQL statements.

Although this tool was designed for analysing SQL, another un-intended benefit, is general troubleshooting.

This dialog can reveal some interest things, just browsing the application can trigger database updates, such as read audit insert/updates in Siebel 8, docking inserts and unexpected write records.

I hope this encourages people to think more about the SQL cost of their config, and proactively address any issues before it becomes a BAU problem.

Troubleshooting
ActiveX warning


This dialog needs to be accepted. The profiling feature needs ActiveX to function.

IE Settings

If you are still having problems. Go into your IE Trusted Zone security settings, and enable the above options.

Remember to add impossiblesiebel.com and your localhost to your trusted zone.

ImposSiebel Toolbar, Version 0.52 Release Information

ImposSiebel Toolbar, Version 0.52 Release Information


[Installation]


[New Features]

  • Introduced SQL Profiler
    Keep an eye out for the next article, and i'll provide a tutorial on how to use this functionality.

  • Added UI Search Spec information to About View
    This search spec is in addition to what you configure in your Applet and BCs. Apply a PDQ, put some dynamic code in the PreQuery event or simply run a query, and you'll see what i mean.

    This feature will display the search spec that is applied during runtime.

    Note. The actual Applet and BC search specs have not yet been implemented.

[Changes]

  • Removed Set PA/Get PA buttons
    Setting and getting profile attributes can be accessed through the menu.

  • Removed About View button
    To streamline the user experience, the About View functionality can be accessed by double clicking on any free space in the main view. SI users currently still have to use the menu for About View.

  • Added life meter
    This shows that the toolbar is running in the background. When this stops, or there is a red box next to it, the Toolbar has encountered an error and needs to be restarted.

[Known issues with Toolbar]

  • Issue: Refreshing IE or clicking Back disables all application hooks.
    Recompiling Tools also causes IE to be reloaded and will have the same effect.
    Cause: This is standard IE behaviour and cannot be avoided.
    Resolution: Restart IE.

  • Issue: A red marker is appearing next to the IS button.
    Cause: An unexpected error has occurred.
    Resolution: Restart IE, and report steps to reproduce to [email protected]

  • Issue: About View dosnt appear.
    Cause: This happens in a view with a lot of vertical scrolling. About View appears near the top of the main view.
    Resolution: Scroll up to see the About View dialog.

  • Issue: All my ActiveX has dissappeared.
    Cause: ActiveX hasnt been cleaned up.
    Resolution: No worries. Double click on a free area of the view, and when About View appears, click [X] to close it, this will restore the ActiveX

[Known issues with SQL Profiler]

  • Issue: SQL Profiler always returns 0 Cost.
    Cause: 1. The wrong spool file is supplied or 2. Two thick clients are open at the same time and have severed links to the spool file.
    Resolution: Close down all thick clients, and only start 1 thick client session.

  • Issue: ActiveX warning always appears.
    Cause: The toolbar needs ActiveX to profile the SQL.
    Resolution: Click Okay to accept, add ImpossibleSiebel.com to your IE browser trusted zone, and add your localhost to your trusted zone.





















 Legend
Working  
Not available  
TBA  































 Compatibility
Siebel 7.8+  
Siebel 8+  
Siebel < 7.8  
Siebel eService  
Siebel Employee Relationship management  
Siebel Call Center  






































































































































 Features HI SI
About View    
Invoke applet method    
Invoke BC method    
Invoke application method    
Invoke control method    
Set UI field    
Get UI field value    
Set profile attribute    
Get profile attribute    
Show current user personalization    
Resize window    
Reload personalization    
SQL performance profiling    
Display UI Search Spec    
Set read only fields    
Toggle applet labels into field names    
Browser script tracing    
Show label/field/column table info    
Create applet level menus    
Draggable and position sensitive dialogs    
MVG, Popup applet support    
List applet interaction support    
Display Applet and BC Search Spec    
Config Repository Search    
Perform Config Review