Introduction
In this article, I would like to share an idea to solve a problem that occurs during the upgrade of an old Siebel version.
This Problem usually affects upgrade projects with IP15 or older versions.
Before OpenUI, Browser Scripts were the only way to write client-side scripts in Siebel. It was used mainly on Applets but there were occurrences for business components or for the application.
These Browser Scripts should be replaced with OpenUI manifested JavaScript codes. In Siebel IP16 or above, these obsolete Browser Scripts, although they are supported by OpenUI, aren’t recommended.
https://docs.oracle.com/cd/E95904_01/books/ConfigOpenUI/appendix_b_reference29.html
Oracle suggests, that the Browser Scripts should be refactored to OpenUI.
I wanted to achieve a general, object-oriented, and logically well-built solution, with the approach of, staying in Oracle`s OpenUI architecture, and try using the best of its features.
The task
I was working on a project with many of these Browser Scripts and the OpenUI was just getting introduced in its IP15 environment. The goal was to replace all Browser Scripts with a corresponding OpenUI solution. We were speaking of more than 50 Applet and 2-3 Business Component scripts.
It is possible to implement every logic in OpenUI but requires some refactoring, since it has a completely different structure. The labor cost in this case would significantly increase with the number of scripts to be migrated. I wanted to come up with a more general solution that could improve the efficiency of the migration.
With a new solution, the syntax and codes of Browser Script could be kept and reused in the OpenUI environment.
The idea
The idea was to use a proxy or a wrapper as an interface between Browser Script and OpenUI logic and fortunately OpenUI supports classes and an object-oriented approach.
The first challenge was to find a way how the Browser Script Methods could be invoked in OpenUI.
I will demonstrate the details later, but here is an example: When I refer to “Applet_PreInvokeMethod” in OpenUI, it should behave the same as in Browser Script.
Although, it would be relatively easy to migrate with a guideline, the chances of failure will increase when it must be done 50 times. With a translator or a wrapper, these repetitions and the risk of copy-paste errors can be avoided.
First, we summarize the statements of OUI and BS.
Here is a partial list of these differences in the statements:
this.FindControl(„controlname„) | var ctrls = this.Get(„GetControls”)
ctrls[controlname] |
this.BusComp() | this.Get(„GetBusComp”) |
this.BusComp().GetFieldValue(fieldName) | var bc = this.Get(„GetBusComp”); bc.GetFieldValue(fieldName); |
this.BusComp().WriteRecord() | var bc = this.Get(„GetBusComp”); bc.WriteRecord(); |
confirm(„text”) | var answer = SiebelApp.Utils.Confirm(‘text’); |
alert(„text”) | SiebelApp.Utils.Alert(„text”); |
theApplication().GetProfileAttr(„Attr”) | SiebelApp.S_App.GetProfileAttr(„Attr”) |
theApplication().SetProfileAttr(„ActBusCase”, „TRUE”); | var bs = SiebelApp.S_App.GetService(„DEMO OpenUI Services”);
var psInput = SiebelApp.S_App.NewPropertySet(); psInput.SetProperty(„AttributeName”, „ActBusCase”); psInput.SetProperty(„AttributeValue”, „TRUE”); bs.InvokeMethod(„SetProfileAttribute”, psInput); |
return („CancelOperation”); | returnStructure [„CancelOperation”] = true; |
return („ContinueOperation”); | returnStructure [„ContinueOperation”] = true; |
this.InvokeMethod(„CheckRufRUEExist”); | SiebelApp.S_App.GetActiveView().GetApplet(this.GetObjName()).InvokeMethod(„CheckRufRUEExist”); |
The next step was to build a context, where all the BrowserScript lines would be “OpenUI-functioning”.
Thanks to OpenUI and the modern Javascript architecture, a parent class was introduced.
At this point, I would like to write a few words, about how this OpenUI architecture provides us an environment, which we may call object-oriented. There are many documents and articles about the principles of OpenUI, like what a Presentation Model or a Physical Renderer is and their recommended usage. However, the core logic and how OpenUI is built are a bit weakly documented. Javascript is not an Object-Oriented language but is certainly capable of something similar. This is aided by the technologies like constructor objects and prototypes in JS. Oracle also used these when they were designing the basic architecture, this Class-Based solution can be used for any custom solution.
The solution
I have written a new Presentation Model class: BrowserScriptPM.js and BrowserScriptListAppletPM.js
It has some implemented methods, but it is an abstract interface class in general and should only be used as a superclass.
List of BrowserScript methods and their corresponding OpenUI method:
Applet Browser Script Methode | OpenUI Object | Method/Event | List/Form Applet |
Applet_PreInvokeMethod | PM | Method: InvokeMethod | List + Form |
Applet_ChangeFieldValue | PM | Method: FieldChange | List + Form |
Applet_InvokeMethod | PM | Method: PostExecute | List + Form |
Applet_Load | PR | PR Method: ShowUI | List + Form |
Applet_ChangeRecord | PM | Event:
Select Row |
List |
Applet_ChangeRecord | PM | Method:
ShowSelection |
Form |
This PM acts as a base PM class for every applet which had BrowserScript.
For instance, we have the following applet with browser script “Applet_InvokeMethod” implemented:
EVO TT Account Trouble Ticket List Applet
How can we migrate it to OpenUI? A possible solution is to write a whole new PM and set everything up to achieve the same logic as it was in the browser script.
With the help of our parent abstract class, it`s enough to create a new PM with the following code:
How does it work? Trough the base class, it is functioning with the following statement:
upon this idea, the parent class prepares every browser script call.
It consists of implementation for the interface and an abstract method declaration that could be implemented in child classes:
An extra wrapper for “theApplication” object was also required to avoid code reformatting.
Conclusion
With this method, we achieved our goal to migrate the scripts, and we also introduced a neat feature of OpenUI and Javascript. As a result, an applet script should take no more than 3-5 minutes. The task was reduced not more than to register the new PM and copy-paste the browser script into the PM template.
When an error occurred in the logic, it was an easy fix because only the parent abstract class needed some adjustments.
As a bit of advice, always try to take into consideration creating a parent super class for such solutions.
Now we can:
- keep our codes better organized
- adjust and modify code easily
- avoid repetition
- use these structured classes as a template and reduce spaghetti code
In this particular case, it was worth it. But if there were less than 10 Browser Scripts, I`m not sure if I would recommend building a similar framework but I would certainly think about it in in any other case.
Gábor Káli – Senior CRM Developer