tag:blogger.com,1999:blog-69921292938706582912024-03-22T00:18:29.424+11:00Impossible SiebelJason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.comBlogger115125tag:blogger.com,1999:blog-6992129293870658291.post-67278536594635425222016-03-31T23:10:00.000+11:002016-05-10T10:12:15.211+10:00Underestimating the Underdog - Siebel 16 & The Steve Watson Story<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSqY20_JQBhgF6clEaWOJQyYEti4IJZBGTc-7v5o4mabQKwxaJ3HQcTKuk_-RN2UcKypW9034F-7BtcBIqmf17Feg1klHKEaZIuvcy6FBss-hHMunoB7MEdPlx7_4ovT5IsqslN0peqWjx/s1600/campaign_banner_New.jpg" imageanchor="1"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSqY20_JQBhgF6clEaWOJQyYEti4IJZBGTc-7v5o4mabQKwxaJ3HQcTKuk_-RN2UcKypW9034F-7BtcBIqmf17Feg1klHKEaZIuvcy6FBss-hHMunoB7MEdPlx7_4ovT5IsqslN0peqWjx/s640/campaign_banner_New.jpg" width="640" /></a><br />
<br />
As part of our syndication arrangements with the Siebel Hub team, the following article has been kindly been allowed to be published here. Since a large portion of the Impossible Siebel readers are Americans, this Siebel event should have particular relevance.<br />
<br />
<hr />
<br />
As we all know Siebel used to be the talk of the town, the cock of the walk, the top dog in CRM. Sadly, that is no longer the case. Siebel is now the underdog. But this dog can still hunt! <br />
<br />
Certainly Oracle is doing its part. The success of Open UI has sparked a Siebel Renaissance. Now Oracle is telling certain customers they can expect Release 16 in April. <br />
<br />
To mark this achievement, along with Eagle Creek, the Siebel Hub has put together a very special event for April 13th. It will feature an update on the state of Siebel, a briefing on Release 16, and a special guest former Denver Bronco Steve Watson. Because you can’t spend too much time with world class people! <br />
<br />
Like Siebel, many people were tempted to count Steve out during his football career. He was cut from his junior high team. No major college recruited him. He was not drafted by the NFL. But he persevered to become the league’s leading receiver. <br />
<br />
It should be a great program; but it would be even better if you came. <br />
<br />
Where: <br />
<br />
Great Northern Tavern<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
8101 E Belleview Ave, Suite E<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
Denver, CO 80237<span class="Apple-tab-span" style="white-space: pre;"> </span> <br />
<br />
When: <br />
Wednesday April 13th, 2016 5:00 P.M. - 8:00 P.M. <br />
Or<br />
<a href="http://info.eaglecrk.com/2016-CO-Siebel-Event-in-Denver-April_CO-Siebel-Event.html">http://info.eaglecrk.com/2016-CO-Siebel-Event-in-Denver-April_CO-Siebel-Event.html</a><br />
<br />
Please feel free to extend this invitation to anyone who might be interested in attending.<br />
<hr />
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-78953253377050648562015-11-25T23:51:00.001+11:002015-12-09T22:32:06.780+11:00Asynchronous Workflow With Real User Login<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRmnrFmJv3_q8-0RHvtJzR8d2OA2d42dq36CPWktUwu3Ms4zK-tJbvBktQ1m0J7NY8fe3KiAMY_CHxMLswHawjhP2kgAsVWR3_3mbnGy3DzlZn7gKsSLVvyCJSMfzvFWGL3RwGxH8XEBJ/s1600/Impersonation+With+Real+User.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRmnrFmJv3_q8-0RHvtJzR8d2OA2d42dq36CPWktUwu3Ms4zK-tJbvBktQ1m0J7NY8fe3KiAMY_CHxMLswHawjhP2kgAsVWR3_3mbnGy3DzlZn7gKsSLVvyCJSMfzvFWGL3RwGxH8XEBJ/s640/Impersonation+With+Real+User.png" width="640" /></a></div>
<br />
<h3>
<b>Background</b></h3>
<br />
A common requirement amongst many Siebel customers, is to have the ability to run an asynchronous workflow under the real
user's login.
<br />
<div>
<br /></div>
This issue is highlighted in the following Oracle support web document, and is representative of the problems faced by many
customers.
<br />
<br />
<blockquote class="tr_bq">
<a href="https://support.oracle.com/epmos/faces/DocumentDisplay?parent=DOCUMENT&sourceId=1244325.1&id=744259.1">NOTE:494815.1
Setting CREATED_BY to the user that invoked the workflow process asynchronously</a>
</blockquote>
<div>
<br /></div>
The customer stated that they have an asynchronous workflow, and wanted to know if it was possible to set the creator login
of a server request. The solution offered by the support personnel was to run the work flow in synchronous mode.
<br />
<div>
<br /></div>
Asynchronous workflows are used in Siebel to offload work from the user session to perform background processing, however
that leaves an undesired effect of stamping the record with SADMIN. This behavior obscures information about the creator,
updater, and prevents audit trail from being utilized.
<br />
<div>
<br /></div>
Workflows can be run synchronously as suggested in the Oracle support web document above, but it has the rather
unwanted effect of blocking the UI.
<br />
<div>
<br /></div>
Fortunately, for customers who can't accept running background tasks synchronously, there is a viable solution, but it
requires a little bit of effort.
<br />
<div>
<br /></div>
<h3>
<b>Requirement</b>
</h3>
<br />
To re-affirm the requirement, we are going to walk through a solution that allows any workflow or business service in
Siebel to be run asynchronously, under the actual users credentials, and without actually supplying the password!
<br />
<div>
<br /></div>
If we step back, and look at the problem from an architectural perspective, we know that when the user logs into the
Application and executes any type of code such as eScript, or workflow, it will run synchronously
under the users application object manager, and it will operate under the users own credentials.
<br />
<div>
<br /></div>
The only supported method to run code and avoid blocking the UI, is to run code under a background process, however any
code that is run in the background will operate under SADMIN by default.
<br />
<div>
<br /></div>
The first challenge is to find a supported method to execute code in a background session under the current users
credentials. Experienced Siebel Integrators in the audience can probably guess, that we can achieve this with any Siebel API that
supports SSO, or utilize the inbuilt impersonation capability of certain Siebel components.
<br />
<div>
<br /></div>
The two most suitable choices are:
<br />
1. Siebel WS
<br />
2. Siebel JDB
<br />
<div>
<br /></div>
I've highlighted these particular interfaces, because both provide APIs that can be invoked from a background session,
and has the potential to allow arbitrary code to be dispatched, and run under a different set of credentials. As an added
benefit, both of these APIs can be built to support load balancing for high availability.
<br />
<div>
<br /></div>
With a suitable SSO API identified, we have the necessary key piece required to solve the above problem.
<br />
<div>
<br /></div>
<h3>
<b>Solution Overview</b>
</h3>
<br />
The diagram below shows an overview of this proposed solution.
<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFzVjU5e0nbF2WVvIvjHaXT4dVkVL6fpFjREWSkAlw8PUJFeSnWr_ZebX2rfWVz8rYdJXDQicZjphoNiZD6Iv-OV58S9EoRrMjxwwyxtmkba2kzcu6koLhMBLdAO6EbMI3BIu3RU5a46-f/s1600/Image.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">
<img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFzVjU5e0nbF2WVvIvjHaXT4dVkVL6fpFjREWSkAlw8PUJFeSnWr_ZebX2rfWVz8rYdJXDQicZjphoNiZD6Iv-OV58S9EoRrMjxwwyxtmkba2kzcu6koLhMBLdAO6EbMI3BIu3RU5a46-f/s640/Image.png" width="640" />
</a>
</div>
<br /></div>
<br />
1. The user triggers an asynchronous task from the current user session, and is allowed to continue with their work in the
application
<br />
<div>
<br /></div>
2. In the background, A WFProcMgr component on the server executes the process, and calls a bespoke service called
"JLE Session Transport Service" that acts as a wrapper for the transport.
<br />
<div>
<br /></div>
3. A synchronous call is invoked over the transport, using the Siebel API identified above
<br />
<div>
<br /></div>
4. The Siebel API instantiates a new session on behalf of the real user, executes the destination business service, and
returns the results back to the background process.
<br />
<div>
<br /></div>
<div>
<h3>
<b>Siebel API</b>
</h3>
<br />
An important implementation aspect worth considering upfront, is designing a
transport agnostic API for the Siebel developer. The developer should be able to specify the desired subsystem, and the service
should abstract the low level transport requirements, and perform the necessary acrobatics to make the call.
<br />
<div>
<br /></div>
The following diagram shows how a facade is used for invoking the actual SSO interface.
<br />
<br />
<img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ6PVE4fjdIgH1ST_UXz7saYi-tScSJPdsHNV7EJ-S122CzOGEbm7l7_x-eKP7S_1FFRiefri7LCfkketyKH5bNO1CqnZZudicJhaX1Wxp9t6t7Q0qk8k-xW64s9fywjJRdDN8aBF9MocX/s640/Image2.png" width="640" /></div>
<br />
A standard Siebel business service is defined, so it can be substituted in any existing workflow, or hooked into any
existing Siebel trigger. The designer now has to implement the adapter code, and build the interface to communicate with the
relevant SSO interface.
<br />
<div>
<br /></div>
The implementation of interfaces to these Siebel APIs are out of scope of this article, as it requires different spectrum's of design,
involve advanced integration, and require environment dependencies to exist, but the key considerations are provided below for customers who are interested in building this capability.
<br />
<div>
<br /></div>
Depending on which SSO API is chosen, you may require an Integration specialist to implement a WS/BS dispatch wrapper, or a
Siebel EAI/Java specialist to implement the Siebel-JDB bridge.
<br />
<div>
<br /></div>
Please consult with your Siebel Integration Architect for more localized implementation advice.
<br />
<div>
<br /></div>
<h3>
<b>Input Arguments</b>
</h3>
<br />
To support a plug and play design, I propose that all input arguments and child properties passed into this service would
be dispatched to the remote business, in the same way as any other business service in Siebel including workflows.
<br />
<div>
<br /></div>
This design allows us to go into tools, and retrofit this capability to any business service, without redevelopment effort.
It is also deliberately designed to avoid hierarchy changes required for the correct invocation of the destination business
service.
<br />
<div>
<br /></div>
To control the dispatch, lets define a custom child hierarchy, which contains 3 key elements.
<br />
<div>
<br /></div>
1. The user login to impersonate
<br />
2. The destination business service to dispatch to
<br />
3. The destination business method name
<br />
<div>
<br /></div>
The diagram below illustrates the property set structure, with the required information to dispatch the call
<br />
<br />
<img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsO18ECQh8QImuASul3jMAdKV7LjpGV6NvkUDey9OCewUL5MRZK2iDDLimlIBOV8X2ZVC5izvtEvYj3xqNe9Cv9PQTTQAioW7b8sD_AtstDKfgc7qy_hpNAUESkt2XwcpcE965EgKvrCt/s320/Image3.png" width="320" />
<br />
<br />
This special PropertySet can sit at any index, however it should be removed before it is dispatched to the remote
business service, in-case there is logic that is sensitive to property sets with specific indexes.
<br />
<div>
<br /></div>
<h3>
<b>PropertySet Serialization</b>
</h3>
<br />
PropertySets are a Siebel proprietary representation of objects that only exist in memory. In order to send a PropertySet
out of Siebel, and receive it back in, it has to be serialized, de-serialized, and potentially encoded to match transport
constraints.
<br />
<br />
XML is usually used to transfer data between different systems, and Siebel provides methods to convert the PropertySet to
XML, and back, however a more efficient method is to utilize Siebel's own PropertySet to text encoding format, or a utilise a
custom JSON parsing engine in eScript. This minimizes the size of the message, results in less IO, and ensures that request is
sent as efficiently as possible.
<br />
<div>
<br /></div>
<h3>
<b>Error Handling</b>
</h3>
<br />
This is the most critical aspect of the design, as every component in the design has to be proactive in handling, and
bubbling errors back up the chain.
<br />
<div>
<br /></div>
The caller is effectively making a synchronous request/response call between two sessions. Errors at the end of the chain
in the impersonated session, has to be propagated through the transport, to the calling session, which has the responsibility to
handle and log any errors.
<br />
<div>
<br /></div>
It is imperative that each component have guards in place to handle environmental, transport, and general unhanded
exception scenarios, which could cause the call to fail.
<br />
<div>
<br /></div>
This can happen for a variety of reasons including
<br />
<div>
<br /></div>
Component is offline
<br />
Component Maxed Task
<br />
Connection timeouts
<br />
Failed authentication
<br />
Out of resource
<br />
<div>
<br /></div>
The Siebel JDB interface has OOTB capability with extra options for configuring, settings such as retry, and timeouts, to
counter some of the above issues. Customers choosing the Siebel WS API will have to consider implementing the appropriate
mechanisms to guard against transient errors.
<br />
<div>
<br /></div>
<h3>
<b>Load Testing</b>
</h3>
<br />
Both the Siebel WS, Siebel JDB options can be configured for load balancing through virtual server definitions. This
capability allows this solution to scale easily. In practice this only works natively for the WS option, the JDB interface seems to only
get load balanced if sessions are spawned from the thread. An as alternative, the load balancing responsibility for the JDB interface can be offloaded to the SRProc component.
<br />
<div>
<br /></div>
Its important to understand the current expected load, and forecast the expected number of tasks that are needed.
Every invocation can potentially spawn a new session, which could effectively double the amount of threads that the system has to
spawn, along with the increased resource utilization, so it would prudent to involve your performance test team, and environment specialists to ensure that the
application is tuned to handle the extra load.
<br />
<div>
<br /></div>
<h3>
<b>Maintaining Impersonation</b>
</h3>
<br />
One last consideration in this design, is that once the user dispatches the work flow to be picked up in the background, no
part of the invocation chain is allowed dispatch to another server process.
<br />
<div>
<br /></div>
The impact is that the developer needs to ensure that all work flows are run inside the impersonated object manager. If a
server request is initiated, that would then dispatch to a server thread, breaking the impersonation for that particular thread.
<br />
<div>
<br /></div>
<h3>
<b>Conclusion</b>
</h3>
<br />
The above capability was designed and delivered for a customer who needed to meet regulatory audit requirements, to capture
the identity of the users when they performed bulk CRUD operations across the application.
<br />
<div>
<br /></div>
In the past customers who needed to meet this requirement would have chosen to take a hit in performance, and kill
the user experience, while expensive background operations are forced to run in the foreground, or resort to creating extra columns across
entities in the application to separately capture the identity of the user.
<br />
<br />
With a little bit of effort, Siebel customers now
have the option of creating a custom impersonation component, that can run asynchronous tasks under a real user.Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-64371834009866515202015-08-04T17:48:00.000+10:002015-08-04T18:35:15.837+10:00Open UI: Protocol HandlerGetting rid of Active X usage is a priority on Open UI projects, because it allows Siebel customers to embrace more modern browsers, and remain compliant into the future, but one of the last bastions of Active X support in a Siebel Open UI project stems from a requirement to launch executables inside an internal domain.
<br />
<br />
Launching a program on the users local machine, requires browser script code similar to the following to be implemented.
<br />
<br />
<pre class="brush:js">
var sCmd = "notepad.exe text.txt";
var shell = new ActiveXObject("WScript.Shell") ;
shell.Exec(sCmd);
</pre>
<br />As part of an Open UI upgrade review to remove browser script, I recommended to a Siebel customer that they implement a custom protocol handler to get around the above dependence on Active X.
<br />
<br />
Protocol handlers are cross platform, and are supported by the major browsers. Although the term protocol handler is obscure amongst general users, its usage is quite prolithic. Here are some common examples of protocols which are handled by browsers
<br />
<br />
<pre class="brush:js">http://
https://
ftp://
</pre>
<br />
The above protocols are trapped and handled internally by the browser, while other protocols are passed down to the OS to be handled by the default program.<br />
<br />
<pre class="brush:js">mailto://
itmss://
</pre>
<br />
When <b>mailto://</b> is typed in to the browser address bar, it launches the default program which is registered to handle emails. Apple users will also recognize the second protocol <b>itmss://</b>, as it is used to launch iTunes, the subtle suggestion here is, we could use the same technique to launch any executable.
<br />
<br />
Each platform has its own method of implementing protocol handlers, so if you are lucky enough to support mac users on Siebel, you’ll need to look into the appropriate vendor documentation. The MSDN reference provides a good digest for those wanting to implement protocol handlers in windows.
<br />
<br />
<a href="https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx</a><br />
<br />
To implement a handler for a new protocol named <b>jle://</b>, a simple reg file can be created and imported to into the registry.
<br />
<br />
<pre class="brush:js">Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\jle]
@="URL:jle protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\jle\DefaultIcon]
@="C:\Apps\protocol_handler.bat"
[HKEY_CLASSES_ROOT\jle\shell]
[HKEY_CLASSES_ROOT\jle\shell\open]
[HKEY_CLASSES_ROOT\jle\shell\open\command]
@="C:\Apps\protocol_handler.bat" "%1"
</pre>
Replace “jle” with your own protocol, and substitute the path to “protocol_handler.bat” according to your local path. “protocol_handler.bat” is a test file that can be used debug the arguments, to see what gets passed to the invoked program, but you may want to use something more sophisticated than a batch file.
<br />
<br />
<pre class="brush:js">rem protocol_handler.bat file
@echo off
echo %1
pause
</pre>
<br />
Once thats setup, type the the new protocol + program arguments into the browser address bar and press enter. Here’s a screenshot of the protocol handler in action.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6UqgRA3bmD5gV84zxDhmf-AH2C-M9kSpWelRWCMPVKS8X8ndapb1xi09yBwA4FznyZCBPxpJXx16IMYVvMUURakkiotAEL7yYSONMseoEtXGcN0qWKv6kMX_ZgqjTZIerS3ghhOPz_fIL/s1600/jle_protocol.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="401" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6UqgRA3bmD5gV84zxDhmf-AH2C-M9kSpWelRWCMPVKS8X8ndapb1xi09yBwA4FznyZCBPxpJXx16IMYVvMUURakkiotAEL7yYSONMseoEtXGcN0qWKv6kMX_ZgqjTZIerS3ghhOPz_fIL/s640/jle_protocol.png" width="640" /></a></div>
<br />
<br />
When designing the protocol handler, keep in mind that you may want to implement a lookup system, to maintain the flexibility of invoking different programs, without having to register new protocols.
<br />
<br />
This approach was used on an Open UI upgrade to negate the dependence on ActiveX in IP2012+. If you are looking to solve similar requirements on your project, it is important to keep the following points in mind.
<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>Pros</b></td>
<td width="3%"></td>
<td width="3%"></td>
<td width="47%"><b>Cons</b></td>
</tr>
<tr>
<td width="47%">
<br />
<li>No Active X</li>
<li>Works across all browsers, and platforms</li>
<li>Does not need elevated privileges</li>
<li>Launch only registered programs</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%">
<br />
<li>Requires desktop deployment</li>
<li>Requires non Siebel expertise</li>
</td>
</tr>
</tbody></table>
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com8tag:blogger.com,1999:blog-6992129293870658291.post-25530538288444527762015-07-14T23:07:00.001+10:002015-07-18T18:08:59.975+10:00The Harness: Use Cases<ul class="bxslider">
<li><img src="//impossiblesiebel.com/app/bxslider/imgs/TheHarness_promo_small_1.png" /></li>
<li><img src="//impossiblesiebel.com/app/bxslider/imgs/TheHarness_promo_small_2.png" /></li>
<li><img src="//impossiblesiebel.com/app/bxslider/imgs/TheHarness_promo_small_3.png" /></li>
</ul>
<br />
The Harness is a modern Siebel development tool, that was built to help a customers Siebel development team to maximize their efficiency, by reducing the amount of time that is lost through the build, compile, and unit test cycle. It was developed off the necessities of integration development, and evolved from some essential use cases.
<br />
<br />
The Harness is deployed as part of the standard developers tool set, and is currently available to all integrators, configurators and production support staff, along side other necessary tools such as database clients, XML/code editors, source control tools.
<br />
<br />
It has been about two years since the first alpha version was built, and it has matured into a product that is used for development and production support.<br />
<br />
The Harness was originally introduced to readers, in <a href="http://www.impossiblesiebel.com/2013/07/the-harness.html">The Harness</a>, and subsequently in <a href="http://www.impossiblesiebel.com/2013/12/the-harness-case-study.html">The Harness Case Study</a>, in this article, we go through the use cases, and provide videos walk-throughs of common usage scenarios.<br />
<br />
<h3>
<b>Use Case 1 - Expression testing
</b></h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2VnAAYqNxN_vdvQgZd4-tju_iSRn2Z5TCqBcLqb6FbcHqSWbF6LLqs3BpY7WCyYbyxZ_ffhyphenhyphenfvEXhn-Rp1FBOe_1UheaNmMyptKBShz0yxOykYPhbzyKl6uHh4_Ay33mBHSz2dNyKmox1/s1600/Expr_module.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2VnAAYqNxN_vdvQgZd4-tju_iSRn2Z5TCqBcLqb6FbcHqSWbF6LLqs3BpY7WCyYbyxZ_ffhyphenhyphenfvEXhn-Rp1FBOe_1UheaNmMyptKBShz0yxOykYPhbzyKl6uHh4_Ay33mBHSz2dNyKmox1/s320/Expr_module.png" width="320" /></a></div>
<br />
Siebel expressions can be found universally in Siebel, but they can be notoriously difficult to troubleshoot.<br />
<br />
For complex expressions, it is easy to make a mistake, leave out a bracket somewhere, or mis-spell the reference to a field or function, and when Siebel expressions are configured incorrectly, they famously error out silently. This adds significant overhead to the development process, because each change has to be iteratively compiled into the SRF.
<br />
<br />
The Harness provides an Expression module, that allows developers to simulate expressions in real time
<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>The Harness</b></td>
<td width="3%">VS</td>
<td width="3%"></td>
<td width="47%"><b>Vanilla Siebel
</b></td>
</tr>
<tr>
<td width="47%"><br />
<br />
<li>Provides the ability to simulate Siebel expressions in real time
</li>
<li>Supports documented Siebel expressions
</li>
<li>Supports undocumented Siebel expressions
</li>
<li>Supports BC Field, and WF property notations
</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%"><br />
<br />
<li>Expressions cannot be simulated in Siebel
</li>
</td>
</tr>
</tbody></table>
<b>Use Case Video: Expression Tester - Fun with Timestamp</b><br />
<a href="https://www.youtube.com/watch?v=JNH6CnGbAGU">https://www.youtube.com/watch?v=JNH6CnGbAGU</a><br />
<br />
<b>Use Case Video: Expression Tester - Lookup Function</b><br />
<a href="https://www.youtube.com/watch?v=w26Ae9Tnfjc">https://www.youtube.com/watch?v=w26Ae9Tnfjc</a><br />
<br />
<h3>
<b>Use Case 2 - Run eScript on the fly</b></h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJJQpKkYKm957yuk_d_BR7owRy5IRHvSlzUPg8-dZeAwg-Bglx3MeOS7ztgkO3w8gUpv9mA3iiZvxYOnstIBCa0Qlyn6FlqpKI4i0YdQPVAtIPVlIVYNaQIojsHQrWetxBLFwQBtonQapq/s1600/Script_module.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJJQpKkYKm957yuk_d_BR7owRy5IRHvSlzUPg8-dZeAwg-Bglx3MeOS7ztgkO3w8gUpv9mA3iiZvxYOnstIBCa0Qlyn6FlqpKI4i0YdQPVAtIPVlIVYNaQIojsHQrWetxBLFwQBtonQapq/s320/Script_module.png" width="320" /></a></div>
<br />
One of the pain points of Siebel development, is the need to make iterative changes to eScript, which requires the developer to compile the changes into the SRF, launch the thick client, and execute the code to build and unit test code. This is another task that adds significant development overhead.<br />
<br />
The Harness allows developer to build and test eScript on the fly.
<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>The Harness</b></td>
<td width="3%">VS</td>
<td width="3%"></td>
<td width="47%"><b>Vanilla Siebel
</b></td>
</tr>
<tr>
<td width="47%"><br />
<br />
<li>Write, test eScript on the fly using a web browser
</li>
<li>Supports ST and Non ST Script engine
</li>
<li>Supports custom script libraries
</li>
<li>eScript can be run locally, on the server, or asynchronously
</li>
<li>Code indenting, highlighting, JS code hints for Non ST engine</li>
<li>Library feature integrates with JSDoc comments for documentation
</li>
<li>Code can be generated from predefined templates
</li>
<li>Can be used to inspect runtime object variables
</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%"><br />
<br />
<li>Traditional eScript needs to be compiled into the SRF, re-triggered, and retested after each change
</li>
<li>Developers also have the option of using the notepad like client side business service editor</li>
</td>
</tr>
</tbody></table>
<b>Use Case Video: Script Module - Run eScript on the fly</b><br />
<a href="https://www.youtube.com/watch?v=jERcYcguYXA">https://www.youtube.com/watch?v=jERcYcguYXA</a><br />
<br />
<b>Use Case Video: Script Module - Library Search</b><br />
<a href="https://www.youtube.com/watch?v=KNaSWYiIAfo">https://www.youtube.com/watch?v=KNaSWYiIAfo</a><br />
<br />
<h3>
<b>Use Case 3 - A modern Business Service simulator</b> </h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNoe8SQEL3AV0Av0e9ZjZyJUvVgJnm8a1cXFBbIeT76-W88afPKjGzSqmnZWpHjHuphaVfMCDcgMDEQDsl8yLxsHQoemjxoMZ5EvlKxQffwGLlN5OneHvRukUhiICsT3Qyq_7oI8-Nfrz/s1600/Bssim_module.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmNoe8SQEL3AV0Av0e9ZjZyJUvVgJnm8a1cXFBbIeT76-W88afPKjGzSqmnZWpHjHuphaVfMCDcgMDEQDsl8yLxsHQoemjxoMZ5EvlKxQffwGLlN5OneHvRukUhiICsT3Qyq_7oI8-Nfrz/s320/Bssim_module.png" width="320" /></a></div>
<br />
The BS SIM module provides the ability for developers to simulate business services with current application context.<br />
<br />
It also provides modern features such as auto complete, and input property helpers, that makes testing Siebel business service behavior much more fluid.<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>The Harness</b></td>
<td width="3%">VS</td>
<td width="3%"></td>
<td width="47%"><b>Vanilla Siebel
</b></td>
</tr>
<tr>
<td width="47%"><br />
<br />
<li>Auto-complete data for business service names, and business service methods.
</li>
<li>Auto-complete data for business service input arguments, workflow process inputs, and BRP Process inputs
</li>
<li>Supports Siebel expression notation
</li>
<li>Converts XML into SiebelMessage/PropertySet/Hierarchy, as an input into the service</li>
<li>Simulate any business service with current application context
</li>
<li>Can be configured with project specific form prefills
</li>
<li>Test cases can be saved, restored and persisted between sessions
</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%"><br />
<br />
<li>Using Business Service Simulator the developer has to click new record, open the Pick applet, and use a wildcard search to get the service name, or method
</li>
<li>Similarly for input property name/value, the developer has to click new record, open the child applet, click new record, and enter in a each name/value pair
</li>
<li>No input property argument is provided
</li>
<li>Complex hierarchies has to be manually constructed, or shifted from the back of another business service invocation
</li>
<li>Simulation only works under the Business Simulator BO
</li>
<li>Test cases history is not available in the UI, it has to be saved/restored from a file system location.
</li>
</td>
</tr>
</tbody></table>
<b>Use Case Video: BS Sim Module - Autocomplete Fields</b><br />
<a href="https://www.youtube.com/watch?v=xdZKsg4T1kQ">https://www.youtube.com/watch?v=xdZKsg4T1kQ</a><br />
<br />
<b>Use Case Video: BS Sim Module - Form Prefill</b><br />
<a href="https://www.youtube.com/watch?v=Y0lsRU9hNEs">https://www.youtube.com/watch?v=Y0lsRU9hNEs</a><br />
<br />
<b>Use Case Video: BS Sim Module - History, with eScript generation</b><br />
<a href="https://www.youtube.com/watch?v=umfnsBAGaXs">https://www.youtube.com/watch?v=umfnsBAGaXs</a><br />
<br />
<br />
<h3>
<b>Use Case 4 - Manipulating the data layer</b></h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGe6MQ2B7nHB_ACLHvuZqVO3qXSGwZY1cTtsxBrxTIuZpXJyKdtJ3k52XgP6FNMEkJj5fNkgucdRI3pQKdB7PN85wpnwtZwPJ4y3Dh8D4gzBZ6GinID2BE_wEWGB6rFh-JsbEAtzgA6EFC/s1600/Bc_module.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGe6MQ2B7nHB_ACLHvuZqVO3qXSGwZY1cTtsxBrxTIuZpXJyKdtJ3k52XgP6FNMEkJj5fNkgucdRI3pQKdB7PN85wpnwtZwPJ4y3Dh8D4gzBZ6GinID2BE_wEWGB6rFh-JsbEAtzgA6EFC/s320/Bc_module.png" width="320" /></a></div>
<br />
The BC module provides a tool for the developer to interrogate the configuration behind the current view, as they navigate the Application. The Harness automatically detects the application context, and pre-fills the necessary the form fields to manipulate the current record.<br />
<br />
This module a provides developers with the ability to create, update, delete, and query for data behind the UI.<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>The Harness</b></td>
<td width="3%">VS</td>
<td width="3%"></td>
<td width="47%"><b>Vanilla Siebel
</b></td>
</tr>
<tr>
<td width="47%"><br />
<br />
<li>Detects UI context, and allows CRUD operation with a web UI
</li>
<li>Supports non UI context objects
</li>
<li>Tools configuration is exposed through the BC module UI
</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%"><br />
<br />
<li>Developers have to use a combination of "About view", a SQL tool, and Siebel Tools
</li>
</td>
</tr>
</tbody></table>
<b>Use Case Video: BC Set Readonly Field</b><br />
<a href="https://www.youtube.com/watch?v=mu5hJvqyl9I">https://www.youtube.com/watch?v=mu5hJvqyl9I</a><br />
<br />
<br />
<h3>
<b>Use Case 5 - Learning the Open UI API</b></h3>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5M7HfwAbMDsMV-_4zV2Hy9ASJKGaN09NIyOjrzkEM3rFHopcgY2Qb2SfLSjvmVwNIK7RoL0mpLHaeTWj7arhItlciosZF2QhT0mgG1AqL07j-yOvXskTK1MujKzIDBGaUfPpvEgiOssvF/s1600/Oui_module.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5M7HfwAbMDsMV-_4zV2Hy9ASJKGaN09NIyOjrzkEM3rFHopcgY2Qb2SfLSjvmVwNIK7RoL0mpLHaeTWj7arhItlciosZF2QhT0mgG1AqL07j-yOvXskTK1MujKzIDBGaUfPpvEgiOssvF/s320/Oui_module.png" width="320" /></a></div>
<br />
The OUI module provides the Open UI developer with a web UI, that integrates with the Siebel session, displays information about the current Screen, View, BO, BC, Applets, and controls, and allows developers to drilldown into the OUI API.<br />
<br />
Commands can be executed against the Siebel session using the inbuilt console, and the auto-complete box allows the developer to quickly search through multiple levels of API name spaces, and custom libraries.<br />
<br />
<table style="border-bottom-style: dotted; border-top-style: dotted; border-width: 1px;">
<tbody>
<tr>
<td width="47%"><b>The Harness</b></td>
<td width="3%">VS</td>
<td width="3%"></td>
<td width="47%"><b>Vanilla Siebel
</b></td>
</tr>
<tr>
<td width="47%"><br />
<br />
<li>About View with object inspection</li>
<li>Learn the Open UI API by browsing on screen objects.</li>
<li>Console with access to the Siebel session
</li>
<li>Indexes and provides auto-complete search for multiple script libraries
</li>
<li>Automatically probes and displays information, from methods that return data</li>
</td>
<td style="border-right-style: dotted; border-width: 1px;" width="3%"></td>
<td width="3%"></td>
<td width="47%"><br />
<br />
<li>Developers can manually look at source code, or memorize documentation</li>
<li>Open UI developers still have to use About View", and lookup the corresponding configuration in Tools</li>
</td>
</tr>
</tbody></table>
<b>Use Case Video: Open UI API Browser</b><br />
<a href="https://www.youtube.com/watch?v=n-CLyrc_YA8">https://www.youtube.com/watch?v=n-CLyrc_YA8</a><br />
<br />
<br />
<h3>
<b>Other modules</b></h3>
<br />
<b>MQ/HTTP Module</b><br />
<br />
The Harness originated from this humble module. The MQ/HTTP module is an essential module for Siebel EAI/middleware developers. It provides a real time interface for sending/receiving messages across message transports. This specialist module provide important prefills on transport parameters, and message templates, that can be used to quickly setup data, and interrogate interface behavior, with XML aware syntax highlighting.<br />
<br />
<b>IO/Msg Module</b><br />
<br />
The IO/Msg module is another essential tool for Siebel EAI/middleware developers, that allow messages to be generated, inspected, upserted/inserted/synchronised and converted on the fly.<br />
<br />
<b>Server Health Module</b><br />
<br />
The Server Health modules probes the server to provide important information such as the machine that the session is connected to, server disk, memory, and CPU utilization. This has been found to be useful in pin pointing problems in resource constrained environments.<br />
<br />
<h3>
<b>FAQs</b></h3>
<br />
<b>Does it work with HI/Open UI?</b><br />
<br />
The Harness was originally designed to work in HI, and has since been ported over to Open UI. It has been tested against HI 8.1, OUI IP2012, IP2013, IP2014, IP2015<br />
<br />
<b>Does it replace Siebel tools?</b><br />
<br />
No. The Harness augments Siebel Tools, however depending on the role of the developer, they could spend a significant part of the day in The Harness testing interfaces, and writing unit test cases, reverting to Tools to create the necessary foundation objects.<br />
<br />
<b>How long does it take to build such a tool?</b><br />
<br />
2 months to build an alpha version from scratch.<br />
<br />
<b>What kind of skill set do I need to build this tool?</b><br />
<br />
Siebel professionals with expertise in eScript, Web professionals with strong JS, UX, and Java is also helpful<br />
<br />
<b>I would love to have it as part of my collection, can you send me a copy?</b><br />
<br />
Unfortunately for third party Siebel tool collectors, The Harness is an internal product.<br />
<br />
<b>Where can I download it?</b><br />
<br />
The Harness cannot be distributed in its current form.<br />
<br />
<b>Can I trial The Harness?</b><br />
<br />
The Harness doesn't have a trial mode<br />
<br />
<b>Can I take this tool onto my next project?</b><br />
<br />
The Harness contains specific customer code, and integrates tightly with a client library. Key parts of the program has to be ported, and a suitable core library has to be established, for it to be used on a new project.<br />
<br />
Contact me on Linkedin, if you are interested in knowing more.<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-32033116050739879112015-05-22T00:05:00.000+10:002015-05-22T00:07:10.313+10:00Advanced Siebel Integration - A SOA Review<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiunPo9mp9f9p1nvKypTHk3ilGOTVoJ4kdR0T1HGN8HWZN3CjlLY2L3FmSW9MN6BJ5vZvepQWsk_aoMLRp7lJmZHy6rU1o0IEPti-mNRNvRQ_jYw-TcLO520jgFFn-YwqQTgDieoO-cNGWH/s1600/Integration+-+SOA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiunPo9mp9f9p1nvKypTHk3ilGOTVoJ4kdR0T1HGN8HWZN3CjlLY2L3FmSW9MN6BJ5vZvepQWsk_aoMLRp7lJmZHy6rU1o0IEPti-mNRNvRQ_jYw-TcLO520jgFFn-YwqQTgDieoO-cNGWH/s640/Integration+-+SOA.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
A recent Oracle SOA review into one of my customers Siebel Integration capability, rated it as highly advanced. The innovative systems, processes, and tools that were put in place, evolved immensely over the years, and enabled the customer to build, deploy, test and maintain their interfaces quickly and with little effort.
</div>
<div>
<br /></div>
<div>
In this organization, the Siebel team provided the front line EAI development, and supported a large portfolio of services across numerous touch points and multiple transport types including MQ, WS, File, HTTP. While adhering to architectural principles such as SOA, P2P, Pub/Sub, this Siebel system plays the role as a consumer, subscriber, publisher, and router of services.
</div>
<div>
<div>
<br /></div>
The environment mix, architecture, and scale may differ in your organization, but there are some fundamental challenges that all Siebel Projects face.<br />
<div>
<br /></div>
<b>High Level Challenges</b>
</div>
<div>
<br /></div>
<div>
- Simplify and standardize Integration
</div>
<div>
- Reduce Integration expenditure
</div>
<div>
- Agility and Time to market
</div>
<div>
<br /></div>
<div>
<b>Simplify and standardize Integration</b></div>
<div>
<br /></div>
<div>
From a high level, there are a variety of messaging requirements that we may encounter, including Request/Response, Notification, Async callbacks, Pub/sub, then we have various transports to handle, which may include HTTP, Message queues, file formats. We then have to choose between the various transformation options, and figure out how to generate our message with the correct headers, deal with message dispatch and error handling.
</div>
<div>
<br /></div>
<div>
There are a variety of implementation options, and each developer will have their own approach to solving the above problems, which can lead to non standardized solutions, that overtime becomes difficult to maintain. Reducing the complexity, and standardising the way we implement integration requires a system that helps us to deliver a consistent solution to dealing with the above scenarios.
</div>
<div>
<br /></div>
<div>
A key component of this system is establishing a Siebel Integration competency centre (ICC), which acts to standardise Integration solutions. An ICC can be defined as team that is responsible for the Siebel EAI needs across different streams and projects.
</div>
<div>
<br /></div>
<div>
Another vital component is the integration framework. An integration framework encapsulates all common integration logic, implements standard design patterns, minimises customisation, coding, and minimize deviation from the standard design entry/exit points. A good integration framework provides the ability to integrate a lot of different technologies, and is instrumental in enabling projects to simply their Integration.
</div>
<div>
<br /></div>
<div>
<b>Reduce Integration expenditure</b></div>
<div>
<br /></div>
<div>
Some organisations approach integration on a case by case basis. The work is put together in an adhoc manner to achieve a certain result, and the grunt work is then repeated on the next project. Issues such as maintenance, error handing, and robustness, unfortunately is an after thought. This causes a lot duplication, waste, increases cost, maintainability, and risk.
</div>
<div>
<div>
<br /></div>
An alternative approach is to look at introducing an integration factory. The concept of an integration factory, is not dis-similar to how car factories mass produce vehicles using standard core components, where robots perform the heavy lifting and mundane tasks on a production line, and engineers move in to perform the specialist tasks that require finesse and skill. This results in a consistent and quality deliverable, that is cost effective.
</div>
<div>
<br /></div>
<div>
In the same way a Siebel integration factory, can delegate or automate certain integration chores, to free up the Siebel Integrator to perform more value added tasks. This factory consists of a set of tools and processes which allows projects to churn out interfaces using a cookie cutter approach to reduce integration build and test.
</div>
<div>
<br /></div>
<div>
Under this approach, less experienced integrators can be used to safely deliver interface work, because the factory enforces a consistent approach to the build. Contrast this with an adhoc build approach, where a less experienced developer is provided with 101 ways to implement something simple like validation, and countless ways to trigger, and implement automation. We can imagine the outcome will be inconsistent, to say the least, and is likely to result in increase costs for the next project who has to maintain this work.
</div>
<div>
</div>
<div>
An Integration factory provides tools to work with messaging requirements, scaffolding for quick deployment of interfaces, and a controlled process to produce interfaces. Integration artefacts such as VBCs, Inbound, Outbound, Request/Response interfaces all have a certain flavour, and are produced with the same common components, and are orchestrated to meet a requirement.
</div>
<div>
<br /></div>
<div>
By applying standardisation, establishing reusable components, and using proven design patterns to solve known problems, we can reduce the cost and risk of implementing integration.
</div>
<div>
<br /></div>
<div>
<b>Agility and Time to market</b></div>
<div>
<div>
<br /></div>
Many Siebel projects need to support rapidly changing business requirements, and deliver on future initiatives at the same time. Integration is traditionally seen as risky, costly, and usually delegated to major releases, which limits the ability to be agile and deliver solutions quickly.
</div>
<div>
<br /></div>
<div>
One of the keys to agility in Siebel is to keep logic out of the SRF, and fortunately Siebel provides a lot of options to configure EAI capability on the fly.
</div>
<div>
<br /></div>
<div>
Client side business services
</div>
<div>
<br /></div>
<div>
Client side business services allow Siebel customers to configure and deploy technical logic to a run time database. This capability allows project to change logic on the fly, and maintain a 24/7 application. There are customers that purely use Client side business service because of the agility advantages over eScript.
</div>
<div>
<br /></div>
<div>
Siebel Workflows
</div>
<div>
<br /></div>
<div>
Siebel workflows are the work horse of automation in Siebel, it provides a nice interface with a visual representation of customer logic. Workflows can be configured and deployed to a run time database, allowing projects to switch workflow definitions on the fly, and apply logic changes without downtime.
</div>
<div>
<br /></div>
<div>
Business Rule Processor (BRP)
</div>
<div>
<br /></div>
<div>
BRP was designed as declarative replacement for eScript, and allows projects to build application logic using a browser. These rules are then executed by a highly optimised engine that works beneath the Siebel BO layer to maximise logic execution. BRP rules can configured and deployed using the Siebel thin client.
</div>
<div>
<br /></div>
<div>
Data Mapper
</div>
<div>
<br /></div>
<div>
Datamapper is Siebel’s declarative engine that performs an object to object transformation. Data map transformations can be also configured using the Siebel thin client.
</div>
<div>
<br /></div>
<div>
Runtime Integration Objects
</div>
<div>
<br /></div>
<div>
Integration objects are representations of a model in Siebel, which is usually built using Siebel tools, and compiled into a SRF. However, with an appropriately connected thick client, Integration object definitions can be deployed to a run time database. When runtime Integration Objects are combined with the right mix of EAI technologies, Siebel customers can build and deploy interfaces without downtime.
</div>
<div>
<br /></div>
<div>
XSLT
</div>
<div>
<br /></div>
<div>
Siebel provides XSLT 1.0 as standard out of the box, but customers can easily implement an XSLT 2.0 engine to get access to an expanded set of transformation options, and speed benefits. XSLT provides a powerful declarative transformation alternative to eScript or Data mapper.
</div>
<div>
<br /></div>
<div>
The Siebel product has a solid range of construction tools out of the box, that allow for changes to be deployed without downtime. Siebel customers that make best use of these technologies, have the opportunity to be very agile and reduce the time to market for their solutions.
</div>
<div>
<br /></div>
<div>
<b>Summary</b></div>
<div>
<b><br /></b></div>
<div>
In this article we’ve introduced the high level challenges of Siebel Integration that organisations face. This prepares us for the next set of articles, where we’ll dig deeper, go through real world scenarios, consider solutions that are aligned to the principles introduced above, walk through the features of a Siebel integration framework, and address the following low level challenges.
</div>
<div>
<br /></div>
<div>
- Reducing technical burden
</div>
<div>
- Dependency on external interfaces
</div>
<div>
- Working in disconnected environments
</div>
<div>
- Working within constraints of Siebel product
</div>
<div>
- Reduce scripting and hard coded references<br />
- Improving code quality </div>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com5tag:blogger.com,1999:blog-6992129293870658291.post-36475929817419732242015-05-12T18:35:00.000+10:002015-05-12T19:01:37.939+10:00Oracle Siebel Open UI Developer's Handbook Review<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEFnDpl6fl6lm9r0156guCbtDzPUP0_5_ywVz5DkY4PCBls9Vx8eHojKobzOm_0OMLF0-cJBN6SwQeeQ96zrFRw6flC7MK2Jda_9m6jzD5gZh3qj_P5HDwqbBQCwT2GKoRamZGAk-PcGz_/s1600/Screenshot+2015-05-12+18.11.50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEFnDpl6fl6lm9r0156guCbtDzPUP0_5_ywVz5DkY4PCBls9Vx8eHojKobzOm_0OMLF0-cJBN6SwQeeQ96zrFRw6flC7MK2Jda_9m6jzD5gZh3qj_P5HDwqbBQCwT2GKoRamZGAk-PcGz_/s320/Screenshot+2015-05-12+18.11.50.png" width="246" /></a></div>
<div>
<div>
<br />
Not so long ago, I received a book in the post from our good friends from Oracle (Ford, D & Hansal, A & Leibert, K & Peterson, J, (2015) <i>Oracle Siebel Open UI Developer's Handbook: Oakamoor,</i> P8Tech). I spent a weekend scrutinising the book and came away thoroughly impressed. So here is my perspective of the book.
</div>
<div>
<br /></div>
<div>
As one of the early adopters of Siebel Open UI, I had to learn the product quickly, train internal developers, and establish a build process for working with this new technology. The tools, scaffolding, processes and Open UI knowledge was then passed onto the next generation of developers.
</div>
<div>
<br /></div>
<div>
A lot of effort was put into establishing this internal competency, as it was done at a time when knowledge of Open UI was scarce, Open UI instructors were themselves being trained, so the best way to learn was to look through the source code, and browse the API tree using the browser console.
</div>
<div>
<br /></div>
<div>
Now days training can be arranged quite easily, there are numerous blogs that spread Open UI knowledge, and you could still learn a lot by looking at the source code, so does this new book add any value? I contend that the "Oracle Siebel Open UI Developer's Handbook" provides significant value for the serious Open UI developer.
</div>
<div>
<br /></div>
<div>
"Oracle Siebel Open UI Developer's Handbook” is a comprehensive book, and its likely that you’ll need to read over many times to really gain benefit from it, there are sections that you’ll skim over because it may not be relevant in your current role, but its comprehensiveness is part of its broad appeal. The book covers Open UI basics, manifest, PM/PR, architecture, installation and deployment, visualisations, CSS themes, advanced scripting, integration and even mobile development.
</div>
<div>
<br /></div>
<div>
Much has changed since I delved into the product that was then IP2012. The whole development team was sent on Advanced Open UI training, and since then only a handful of lucky people got to work with the technology. The half of the team that actively works with the technology are certainly more skilled than the other half that hasn’t use their training. This book appeals to both markets, as it is aimed squarely at the developer, and doesn’t make any assumptions about the level of the reader.
</div>
<div>
<br /></div>
<div>
Siebel projects around the world would have a similar mixed bag of Open UI knowledge. IP2012 is now superseded by IP2013, and IP2014 and the product has evolved quite drastically, so your skills might not be where you think it is. This book provides a great chance for Open UI professionals to learn the latest developments from the Open UI product or solidify their existing knowledge, without going through further training.
</div>
<div>
<br /></div>
<div>
Alternatively developers can invest a bit of time going through bookshelf, and trawl through all the articles on the web to self learn Open UI, it is certainly possible, but learning Open UI is not a natural stepping stone for many Siebel developers, and for the seasoned developer like myself, who is quite time poor, I found the book to be an excellent investment of my time, and wished I had it when I first learned Open UI. <br />
<br />
This book adds great value, as you learn Open UI from the 4 of the best Open UI experts in the world. If you like @lex’s work on Siebel Essentials (Siebel Hub), then this book is more of the same awesomeness, but packaged for the Open UI professional.
</div>
<div>
<br /></div>
<div>
Get it here from Amazon
</div>
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<br />
<div>
<a href="http://www.amazon.com/Oracle-Siebel-Open-Developers-Handbook/dp/099291051X">http://www.amazon.com/Oracle-Siebel-Open-Developers-Handbook/dp/099291051X</a></div>
</div>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-79240401460854464872014-10-23T00:11:00.001+11:002014-11-08T15:11:33.593+11:00Open UI: Testing with Selenium<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqtUlOyVkmwNZ4Zd4TiEssAQBj4-z2SJYM65JP3bnZvYCeN-vOKp4IpA9S2EV5pXTAOfUW82u0zQWWmIaQfe0e5GD-C-Cmrnz79jPul_iD2Ak5yQwWmbTG36j1GIc7ayqLBI9lI_LNjZA1/s1600/big-logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqtUlOyVkmwNZ4Zd4TiEssAQBj4-z2SJYM65JP3bnZvYCeN-vOKp4IpA9S2EV5pXTAOfUW82u0zQWWmIaQfe0e5GD-C-Cmrnz79jPul_iD2Ak5yQwWmbTG36j1GIc7ayqLBI9lI_LNjZA1/s1600/big-logo.png" height="180" width="200" /></a></div>
Selenium is a browser automation tool, that allows web projects to automate repetitive tasks. As an early pioneer of Open UI, I found this new capability to be incredibly useful for achieving continuous integration. I gave readers a hint of this last year, in the article <a href="http://www.impossiblesiebel.com/2013/10/open-ui-build-process.html">"Open UI - Build Process"</a>, which left readers with a list of ingredients, and a plan to manage their build automation.
<br />
<br />
Now that more Siebel projects around the world are on embarking on upgrading their Siebel Applications to Siebel Open UI. Its about time we advance this concept into something more tangible that Clients can benefit from.
<br />
<br />
Picture this... as part of the Open UI upgrade, you are required to navigate to 1000+ views in Siebel and test for WCAG defects in all 3 major browsers. That isn't so exciting.<br />
<br />
Testing for Open UI defects requires a high level of thoroughness to ensure that entire your Application is compliant, and remains compliant in the future. The move to Open UI will expose poor configuration practices that might have been passable in HI, but will break in Open UI. Open UI will also introduce defects as a side effect of the upgrade.
<br />
<br />
The simple approach to this problem is to brute force it, and assign a team of developers to navigate to each view to analyse for technical defects. But this isn't really viable, as a long term strategy, a smarter approach is to use web automation.
<br />
<br />
Web automation brings to mind images of robots that are used to scrape web sites, harvest email addresses and index content, but Siebel developers have a more important itch to scratch: Testing the Siebel UI.
<br />
<br />
The obvious use case is to run continuous integration testing, to ensure that new builds are thoroughly tested over night. A more advanced crawler can be built to perform functional testing of the applications main areas, but the scope of this article is to show how you can build your own Open UI crawler that can be used to programatically navigate to each view, and optionally validate your application.
<br />
<br />
Theres no shortage of tools in the market that is available to perform this sort of work, but if we narrow our criteria to open source web automation solutions, the Selenium web driver makes a pretty good choice, as it's also set to become a W3C recommendation. Selenium works with all the major browsers, is compatible with your favorite programming language, and it is also free.
<br />
<br />
This article will provide you with a sample application that implements Open UI automation with Ruby, but you can extract the lessons learnt from this article, and implement them in your language of choice.
<br />
<br />
I've chosen to use Ruby as my language, because there is solid support for web automation. Ruby has gems that allow the developer to easily parse the DOM, make selections using CSS or XPath syntax, deal with dialog boxes, and take screen shots of problem views. Combining with this Watir, which is a selenium wrapper in Ruby, allows the developer to build the automation quickly in a light weight language.
<br />
<br />
The solution for your project may be different, if you require enterprise support, headless servers, or if you plainly prefer to stick to your language of choice, because of your available skill set, then the right tool for your circumstance will be different. The most important ingredient here is Selenium, or in this case Watir, which is a Ruby flavor of Selenium.
<br />
<br />
<b>Selenium
</b><br />
<br />
This is the Browser automation API that allows you to control your browser programatically
<br />
<br />
<a href="http://www.seleniumhq.org/">http://www.seleniumhq.org/</a><br />
<br />
" Selenium automates browsers. That's it! What you do with that power is entirely up to you. Primarily, it is for automating web applications for testing purposes, but is certainly not limited to just that. Boring web-based administration tasks can (and should!) also be automated as well."
<br />
<br />
<b>Browser Support
</b><br />
<br />
Chrome, Firefox, IE...
<br />
<br />
<a href="http://www.seleniumhq.org/about/platforms.jsp#browsers">http://www.seleniumhq.org/about/platforms.jsp#browsers</a><br />
<br />
<b>Remote control drivers
</b><br />
<br />
Javascript, Java, C, Ruby, Perl, PHP...
<br />
<br />
<a href="http://www.seleniumhq.org/about/platforms.jsp#programming-languages">http://www.seleniumhq.org/about/platforms.jsp#programming-languages</a><br />
<br />
<b>Open UI
</b><br />
<br />
The crawler can be run against a thin client, or against a local thick Client running Open UI.
<br />
<br />
<b>Ruby Implementation
</b><br />
<br />
Knowing Ruby isn't a prerequisite to understand this concept. Ruby is a pretty readable language, and I've added a good dosage of comments to explain what the code is doing so those from non Ruby backgrounds can follow.
<br />
<br />
<pre class="brush:js">#import required libraries
require 'rubygems'
require 'watir-webdriver'
require 'cgi'
#Parametise the URL that will be used to navigate to the Open UI application
#This should really be configured for a server URL for real testing
#but im using a local URL for this example
sURL = "http://localhost/start.swe?"
sPass = nil
sUser = nil
#Open a new chrome browser session
browser = Watir::Browser.new :chrome
#navigates to the URL defined above
browser.goto sURL
#maximise the window so we can see all entire view
browser.window.maximize
#This block simulates the user login process for thin client connection
#else it is bypassed for the thick client
if sUser!=nil && sPass!=nil
#fill in username in the user name field
username = browser.text_field(:name, "SWEUserName")
username.set sUser if username!=nil
#fill in password in the password field
password = browser.text_field(:name, "SWEPassword")
password.set sPass if password!=nil
sleep 1
#click the login button
browser.link(:text =>"Login").when_present.click
end
sleep 5
</pre>
<br />
Congratulations!. At this point we have just created a simple crawler that has logged into an Open UI Application.
<br />
<br />
Next we want to tell it how to navigate the application, by going to the sitemap, read all the views, and parse all the JS links embedded in the view elements. This is done pretty easily in Ruby.
<br />
<br />
<pre class="brush:js"> #use CSS to locate sitemap icon, and click it
browser.element(:css => "li[name=SiteMap] > img").when_present.click
#use CSS selector to read all the views in sitemap into an array
#these links also contain an onclick attr that allows to emulate a view navigation
links =browser.css("span[class='viewName'] > a")
</pre>
<br />
Finally, we loop through every link, execute the JS code to perform the navigation, and optionally perform any automation.<br />
<br />
<pre class="brush:js"> links.each do |link|
params = CGI.parse(link.attr("onclick"))
sleep 5
#Goto view
browser.execute_script( link.attr("onclick") )
end
</pre>
<br />
Thats as simple as it needs to be.
<br />
<br />
To fire it up with a dedicated client, you'll first need to open up an existing session to start the local web server. When the above code is run, it will launch a new browser connecting to the existing session.
<br />
<br />
For thin client connections, it is not necessary to pre-launch the session, the above code will instantiate a new browser session, and will login in normally.
<br />
<br />
A crawler like the program above, can navigate the application, verify each view and flag views that have issues.
<br />
<br />
Building a simple crawler is a easy, and is something that you can give to an energetic graduate to perform in a day, however if you require a crawler that can be a workhorse for your Continuous Integration strategy, then it needs to be a little more robust, and more scalable than the simple example above, or if your needs warrant a more specialized crawler, that can check for and enforce WCAG compliance in your application, then you'll ideally need a plugin system that can allow you to easily add new validators. If want to go a little further, and build in functional testing capabilities, then could build an API bridge to facilitate a DSL to build more readable test cases.
<br />
<br />
Open UI + selenium opens up these exciting opportunities. For my client, having a nightly build process + continuous integration, and WCAG reporting, ensures they have a strict standards compliant UI and a more stable application for every deploy.
<br />
<br />
This article provides the necessary ingredients, and a simple recipe for other Siebel customers to follow the same path.
<br />
<br />
<b>Further Reading
</b><br />
<br />
<a href="http://docs.seleniumhq.org/docs/03_webdriver.jsp">Selenium Web driver</a>
<br />
<a href="http://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration</a>
<br />
<a href="http://www.w3.org/TR/WCAG20/">WCAG</a>
<br />
<br />
<b>More on Open UI</b><br />
<br />
Serious Open UI developers should be on the watch, for the up comming Open UI book from some very distinguished authors<br />
<br />
<a href="http://www.siebel-essentials.com/2014/07/siebel-open-ui-developers-handbook.html">Siebel Open UI Developer's Handbook</a>
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com7tag:blogger.com,1999:blog-6992129293870658291.post-59256286858713485862014-09-18T00:38:00.001+10:002014-09-18T07:20:11.827+10:00Open UI: Grunt and JSHint<span style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">Previously we looked at how Grunt can improve your Open UI development experience, by automatically reloading the browser, every time a source file is changed. This time we take another step, and configure an automated code check using Grunt and JSHint. <br /><br />Think of how Siebel Tools prevents you from compiling, or checking in poorly constructed eScript. JSHint will do the same (if not better) job of making sure your client side code is free from language errors, and potential problems.</span><br />
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
Starting from where we left off in <a href="http://www.impossiblesiebel.com/2014/09/open-ui-grunt-with-livereload.html">Open UI: Grunt and Livereload</a>, we should have an operational grunt job that reloads our browser. To add JSHint to the mix, we need to modify the package.json file slightly, to include one new line to install this new dependency</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<i>{<br />
"name": "SiebelGrunt",<br />
"version": "0.0.1",<br />
"devDependencies": {<br />
"grunt": "~0.4.1",<br />
"grunt-contrib-watch": "^0.6.1",<br /><b> "grunt-contrib-jshint": "^0.10.0"</b><br />
}<br />
}</i><br />
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
With your command prompt at the directory with this package.json file, type the following command to pull down this module</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
<span style="background-color: #181818; color: #f8f8f8; font-size: 14px; line-height: 20px; white-space: pre-wrap;">npm install </span></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
Now we need to configure the Grunt build process, to register this new task, and configure it so it only checks changed files.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<i>module.exports = function(grunt) {<br />
var sJSPath = '../PUBLIC/enu/*/SCRIPTS/**/*.js';<br />
grunt.initConfig({<br />
pkg: grunt.file.readJSON('package.json'), <br />
<b> jshint: {<br />
scripts: [sJSPath]<br />
},</b><br />
watch: {<br />
scripts: {<br />
files: [sJSPath],<b><br />
tasks: ['jshint'],</b><br />
options: {<br />
nospawn: true,<br />
livereload: true<br />
},<br />
}<br />
}<br />
});<br />
grunt.loadNpmTasks('grunt-contrib-watch');<b><br />
grunt.loadNpmTasks('grunt-contrib-jshint');</b><br /><b>
grunt.event.on('watch', function(action, filepath){<br />
grunt.config(['jshint', 'scripts'], filepath);<br />
});</b><br />
grunt.registerTask('default', ['watch']);<br />
};</i></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
To explain what I've done, this newly added block registers JSHint, and uses the file path that we defined previously</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<i> jshint: {<br />
scripts: [sJSPath]<br />
},</i></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
Next, I register the 'jshint' task with the 'watch' task, which will run JSHint every time a file is changed.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<i> tasks: ['jshint'],</i></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
The only problem with this configuration is that, JSHint has no idea which file was modified under the watch task, so JSHint will run over all 1500+ files under Siebel scripts and lint them all. If this is run without a filter, your command prompt will hang, and after a while it will come back with a window similar to this.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXD_r1Ob_3bo9A0dxdywRcc4fZdGDJNLmgc0blUlCNXF91qqm7cckXiy00h1DXVSsuiJ2z5D8qTgIGYLVRM7nc8d4ZCQVjFv6lL2l_cA2vpimWQ9_uB0leulQ_qwWwk3TfXZaPw7xJ9cfx/s1600/grunt_1572.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXD_r1Ob_3bo9A0dxdywRcc4fZdGDJNLmgc0blUlCNXF91qqm7cckXiy00h1DXVSsuiJ2z5D8qTgIGYLVRM7nc8d4ZCQVjFv6lL2l_cA2vpimWQ9_uB0leulQ_qwWwk3TfXZaPw7xJ9cfx/s1600/grunt_1572.png" height="160" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
JSHint reports 15K plus errors across all the files under the Siebel scripts folder, but its not all bad, some of the code under Siebel/scripts is 3rd Party which can raise some errors, and the rest will have been through Oracle's own lint process, and then minified before delivery to customers. We should only be concerned with the files that we have control over.<br />
<br />
To make JSHint validate a single file, I added the following block.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<i> grunt.event.on('watch', function(action, filepath){<br />
grunt.config(['jshint', 'scripts'], filepath);<br />
});</i></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
This configures a listener on the watch event, and passes in the name of the modified file to JSHint. <span style="text-align: -webkit-auto;">Now we are ready to roll. Fire up the grunt process.</span></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
<span style="background-color: #181818; color: #f8f8f8; font-size: 14px; line-height: 20px; white-space: pre-wrap;">grunt </span></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; font-size: 14px; line-height: 20px; white-space: pre-wrap;"><br /></span></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
Switch back to your code editor, open up postload.js, and type in every body's favorite command "asdf"</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZLLJefxNx40pbtKL92t-RrruP0qih8s7rZ-gIc7y6eY40ekIFiwC6BtJQdUw659NAW14O44ShGMEaRwui9NoHAXPsjVKBmsbZF7h44pchPSF8i17HhgjbZaoYfHqzz3vNTI3SfrBFoL8H/s1600/grunt_12.png" imageanchor="1" style="font-family: 'Times New Roman'; margin-left: 1em; margin-right: 1em; orphans: auto; text-align: center; widows: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZLLJefxNx40pbtKL92t-RrruP0qih8s7rZ-gIc7y6eY40ekIFiwC6BtJQdUw659NAW14O44ShGMEaRwui9NoHAXPsjVKBmsbZF7h44pchPSF8i17HhgjbZaoYfHqzz3vNTI3SfrBFoL8H/s1600/grunt_12.png" height="173" width="320" /></a></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
Watch will automatically fire JSHint, and report back on the errors, with the line number and a description of the problem. Note that we lost our purple background because our script failed to parse.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
Alright, now lets fix that bug</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EAQgeHIspPL0bHx7GmoolzV_4MHXBwI4nF3vw3JHE-AqT371R3gphCyDGSc3XE_RKpWns2lu5A8Usu9DiIsfpuT7Te2xS0ZN8kgsGCyNsm2Blavouk4x6D3Gkm1a7tPMtTzG5Lz0uGLJ/s1600/grunt_ok.png" imageanchor="1" style="font-family: 'Times New Roman'; margin-left: 1em; margin-right: 1em; orphans: auto; text-align: center; widows: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EAQgeHIspPL0bHx7GmoolzV_4MHXBwI4nF3vw3JHE-AqT371R3gphCyDGSc3XE_RKpWns2lu5A8Usu9DiIsfpuT7Te2xS0ZN8kgsGCyNsm2Blavouk4x6D3Gkm1a7tPMtTzG5Lz0uGLJ/s1600/grunt_ok.png" height="174" width="320" /></a></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
We see that JSHint has reported "1 file lint free", and our browser has automatically reloaded in the background with our purple background again. </div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
JSHint won't make your Siebel developers better web developers. It will only ensure that any code that is written is written with a consistent syntactic style, and that critical language errors are picked during build and unit test, but it will provide you with the coordinates of any errors that is picked up. </div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
JSHint is a great safety net, but remember its recommendations can be ignored. To enforce this on a broader scale JSHint can be configured to run against the entire code base on a regular basis, and its results can be enforced by a QA process.<br />
<br />
In the case above, a small typo caused 12 errors resulting in missing background color, but in other scenarios, these kinds of errors could cause more serious issues, which illustrates the importance of a code quality tool like JSHint.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
Hopefully this article has piqued your interest in Client side build automation. Are you using similar tools on your project, or have you adapted a build process that you would like to share with the Siebel community?. <br />
<br />
Send in your comments.</div>
<div style="font-family: Tahoma; orphans: 2; text-align: -webkit-auto; widows: 2;">
<br /></div>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com1tag:blogger.com,1999:blog-6992129293870658291.post-40332294093529353472014-09-17T00:59:00.000+10:002014-09-17T01:00:52.884+10:00Open UI: Grunt with Livereload<span style="font-family: Arial, Helvetica, sans-serif;">With Siebel Open UI development we naturally spend the majority of our time working on the browser. Part of that requires clearing the browser cache, and hitting F5 to reload the browser.</span><br />
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">Sometimes we reload the browser, and think afterwards, did I really clear the cache that time? Maybe not... so we the clear cache, and reload the browser again. Seconds later, we spot a typo in our code and the endless cycle continues. Wouldn't it be good if we can focus on writing the code, and let something else clear the cache and reload the browser? </span><br />
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">This is where tools like Grunt can help.</span><br />
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<b><span style="font-family: Arial, Helvetica, sans-serif;">1. Download No Cache<br /></span></b></div>
<div><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="orphans: 2; text-align: -webkit-auto; widows: 2;">"No Cache" is a Chrome extension that I wrote to automatically clear your browsers cache. It is available for free on the chrome store. There are 1 click solutions out there, but I prefer to have an automatic background process take care of this.</span></span><br />
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<br />
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="https://chrome.google.com/webstore/detail/no-cache/ogbfmfambmmhfdpfokohebghmcdbodbh?hl=en">https://chrome.google.com/webstore/detail/no-cache/ogbfmfambmmhfdpfokohebghmcdbodbh?hl=en</a><br /></span></div><br />
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
1. Right click on the No Cache icon, and choose "Options"<br />
2. On the "Cache" tab select "Enable for filtered requests"<br />
3. On the "Filters" tab select the input box, type in "start.swe" and click the + icon<br />
</div><br />
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">This tells No Cache to clear the cache for every request Siebel makes, this should work on the local or thin client. If you use another browser and have your own favorite clear cache plug in, then that will work as well.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<b><span style="font-family: Arial, Helvetica, sans-serif;">2. Install Grunt</span></b></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
Grunt is a JavaScript task runner that we can configure to reload our browser, but first we need to download and install Node.js from this website<br /><br /><a href="https://www.blogger.com/goog_153542409"></a></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="http://nodejs.org/download/">http://nodejs.org/download/</a><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;"><br />
<span style="font-family: Arial, Helvetica, sans-serif;">Its not necessary to know what Node.js does, just know that it provides us with the environment to run Grunt. Once you've installed Node.js open a command prompt and type the following line to install the grunt command line globally.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;">npm install -g grunt-cli</span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">Next we need to decide where to put our Grunt configuration. I like to put it under the Siebel/Client folder because I backup the PUBLIC folder, and don't want copies of Grunt and its modules copied along with this backup.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">Open a command prompt, cd to your Client folder, and follow the next set of instructions to install and configure grunt on your local machine.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;">mkdir grunt</span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;">cd grunt</span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">Create a new file in the same folder called package.json, with the following contents<br /><br />
{<br />
"name": "SiebelGrunt",<br />
"version": "0.0.1",<br />
"devDependencies": {<br />
"grunt": "~0.4.1",<br />
"grunt-contrib-watch": "^0.6.1"<br />
}<br />
}</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
back at the command prompt, type the following command to download the required dependencies defined in the file above<br /><br /><span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;">npm install </span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">Next create a new file called Gruntfile.js, with the following contents</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">module.exports = function(grunt) {<br />
var sJSPath = '../PUBLIC/enu/*/SCRIPTS/**/*.js';<br />
grunt.initConfig({<br />
pkg: grunt.file.readJSON('package.json'),<br />
watch: {<br />
scripts: {<br />
files: [sJSPath],<br />
options: {<br />
livereload: true<br />
},<br />
}<br />
}<br />
});<br />
grunt.loadNpmTasks('grunt-contrib-watch');<br />
grunt.registerTask('default', ['watch']);<br />
};</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">This file is important, so lets run through it line by line</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
> var sJSPath = '../PUBLIC/enu/*/SCRIPTS/siebel/custom/**/*.js';<br /><br />
This path specifies the folder and file pattern that Grunt will watch for changes. Essentially we want to watch for any changes to JS files in the Siebel script folders</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">> watch: {<br /><br />
This line defines a "watch" task, there are other tasks that can be run. Eg code lint/minification/, but I've kept it simple for this example.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
> files: [sJSPath],<br /><br />
configure the files to watch using the path statement above</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
> livereload: true<br /><br />
This option will spawn a background process that will cause your browser it refresh automatically. To Integrate our browser with this background process, there are 3 options as described here</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<a href="http://feedback.livereload.com/knowledgebase/articles/87979-how-do-i-choose-the-best-integration-method-"><span style="font-family: Arial, Helvetica, sans-serif;">http://feedback.livereload.com/knowledgebase/articles/87979-how-do-i-choose-the-best-integration-method-</span></a></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">The browser extension is the most suitable method for development, so go ahead and download it with these instructions.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<a href="http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-"><span style="font-family: Arial, Helvetica, sans-serif;">http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-</span></a></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">To start it all up, go back to the command prompt and simply type</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;">grunt</span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="background-color: #181818; color: #f8f8f8; line-height: 20px; white-space: pre-wrap;"><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">To test it out, goto SCRIPTS, open up any JS file like "postload.js", modify it as below, and watch your browser reload magically.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie0T3rg7a-F123DHgbPZLKzD3IUCGZKL0znrzpVzECZRAKOxnfumEcFDGimdgWMNx4E7z03sa8aDflmhqYuFWz0ZwFVDGNVx2GH6zMkCg78KwpiqEPPIQSnSVGCEnjer-2euAjVExIcp0/s1600/nocache_livereload.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie0T3rg7a-F123DHgbPZLKzD3IUCGZKL0znrzpVzECZRAKOxnfumEcFDGimdgWMNx4E7z03sa8aDflmhqYuFWz0ZwFVDGNVx2GH6zMkCg78KwpiqEPPIQSnSVGCEnjer-2euAjVExIcp0/s1600/nocache_livereload.png" height="174" width="320" /></span></a></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">I've presented the bare minimum required to get up and running with Grunt, but once you have that setup, you no doubt want to look into what other things Grunt can do for you.</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">A good place to start is..</span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<a href="http://gruntjs.com/"><span style="font-family: Arial, Helvetica, sans-serif;">http://gruntjs.com/</span></a></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;">Or another tutorial like this one<br /><br /><a href="http://www.smashingmagazine.com/2013/10/29/get-up-running-grunt/">http://www.smashingmagazine.com/2013/10/29/get-up-running-grunt/</a></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
</div>
</div>
</div>Jason Lehttp://www.blogger.com/profile/04790956811233496072noreply@blogger.com2tag:blogger.com,1999:blog-6992129293870658291.post-4060958476858411452014-07-23T21:17:00.001+10:002014-09-18T00:39:29.212+10:00Siebel cScript<b><br /></b>
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVN4fxRkN43OOC3-iR0uJ3YQeoFLhmBu_y7YPJoXg1KkvSH4cR9RSXKWYKztsS2PdTiELSlvHqNR0s9pLyJLfJFxkpVuHR6shuoVqInaVUVMvYEdx4296cffYNvYWDfx_M8-4wSUbk55Pt/s1600/cScript.png" height="72" style="color: #0000ee; text-align: center;" width="320" /><br />
<br />
<b>Introduction</b>
<br />
<br />
eScript is Siebel’s de-facto scripting language, but in an alternate universe, Siebel could have called its scripting language <b>cScript</b>, in reference to its C heritage. eScript is based on the ECMA Script standard (from which JavaScript is also based upon), and shares the same C family style syntax, but it also has uncanny similarities to C that are unparalleled by other ECMA Script derivatives.
<br />
<br />
Here are 5 good reasons, why Siebel could have called its scripting language <i>cScript</i> instead of <i>eScript</i>.<br />
<br />
<b>1. Compiled Code</b>
<br />
<br />
eScript code is compiled, and runs outside of a browser, just like C.
<br />
<br />
<b>2. Pre-processors</b>
<br />
<br />
Pre-processor directives tell the compiler to perform specific actions before the code is actually compiled.
<br />
<br />
A typical C program is constructed like so:
<br />
<br />
<pre style="brush: js’;">#include <stdio.h>
int main(void)
{
printf(“hi”);
}
</pre>
<br />
#include is an example of a pre-processor directive.This tells compiler to import the standard IO library and make it available to the program.
<br />
<br />
Veteran Siebel programmers will also recognise that the same syntax is used in eScript for EAI purposes.<br />
<br />
#include "eaisiebel.js"
<br />
<br />
This pre-processor isn't explicitly documented under the main eScript reference, but it is hidden away under the following section.
<br />
<br />
Siebel eScript Language Reference > Compilation Error Messages > Preprocessing Error Messages<br />
<a href="http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_Troubleshooting6.html#wp1012712">http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_Troubleshooting6.html#wp1012712</a>
<br />
<br />
It is also mentioned in
<br />
<br />
Business Processes and Rules: Siebel Enterprise Application Integration > Data Mapping Using Scripts > EAI Data Transformation<br />
<a href="http://docs.oracle.com/cd/B40099_02/books/EAI4/EAI4_DataMapUSScripts3.html"> http://docs.oracle.com/cd/B40099_02/books/EAI4/EAI4_DataMapUSScripts3.html</a>
<br />
<br />
A small caveat. The #include directive can be written in the following two styles in C.
<br />
<br />
#include <eaisiebel.js><br />
#include "eaisiebel.js"
<br />
<br />
The <> brackets tell the compiler to look in a predetermined directory, while the “”(two double quotes) tell the compiler to look in the current directory as the c program, however in Siebel, when the “” is used, Siebel will look in Tools\Scripts\ for the include file. (Siebel v8+)
<br />
<br />
<b>3. Libraries</b>
<br />
<br />
In the above code sample under <i>Pre-Processors</i>, we saw the usage of a function called “printf”. printf outputs a formatted to the standard console. This isn’t part of the core C language, but was made available via the include pre-processor directive, which imports this command into the program from standard libraries.<br />
<br />
Standard C libraries from stdio.h, stdlib.h, are also available in Siebel, but there’s no need to include them, Siebel has conveniently wrapped these libraries in Siebel and exposed them through the Clib global object.
<br />
<br />
eg.
<br />
Clib.rsprintf – returns a formatted string to the supplied variable. <br />
Clib.fscanf – read data from file stream
<br />
<br />
The complete Clib object reference can be found here<br />
<a href="http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSReference109.html"> http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSReference109.html</a>
<br />
<br />
<b>4. Reference Operators </b>
<br />
<br />
The following example shows how reference operators are used in a C program.
<br />
<br />
<pre style="brush: js’;">#include &lt;stdio.h>
void sub(int* main_int)
{
*main_int=10;
printf("Address sub:\t %d\n",&*main_int);
}
int main()
{
int myInt=5;
printf("Address main:\t %d\n",&myInt);
printf("Before Value:\t %d\n",myInt);
sub(&myInt);
printf("After Value:\t %d\n",myInt);
}
//Results
/*
Address main: 2293340
Before Value: 5
Address sub: 2293340
After Value: 10
*/
</pre>
<br />
<br />
In the above code, an int is given the value 5, its address reference in memory is provided to a sub function using a reference operator
<br />
<br />
sub(&myInt);
<br />
<br />
The sub function takes this reference, goes to its address in memory, and modifies the original value.
<br />
<br />
We can the same functionality in eScript with the following code
<br />
<br />
<pre style="brush: js’;">function sub(&main_int)
{
main_int=10;
}
function main(Inputs, Outputs){
var myInt=5;
Outputs.SetProperty("Before Value",myInt);
sub(myInt);
Outputs.SetProperty("After Value",myInt);
}
//Results
/*
Before Value: 5
After Value: 10
*/
</pre>
<br />
Note: The reference operator in this case is declared in the sub function input argument. This tells Siebel to treat &main_int as a pointer to the original value, instead of a copy.<br />
<br />
<b>5. Memory pointers</b>
<br />
<br />
Like all relatives, eScript and C share common ancesters. In this case, the commonality is in the sharing of memory pointers. <br />
<br />
The following example shows how an invoked C program can modify data inside eScript. This example is sourced from the bookshelf document on SElib<br />
<a href="https://www.blogger.com/%E2%80%9Dhttp://docs.oracle.com/cd/B31104_02/books/eScript/eScript_JSReference253.html%E2%80%9D"> http://docs.oracle.com/cd/B31104_02/books/eScript/eScript_JSReference253.html</a>
<br />
<br />
In summary, a couple of buffer objects are created.
<br />
<br />
<pre style="brush: js’;"> var P_CHURN_SCORE = Buffer(8);
var R_CHURN_SCORE = Buffer(8);
</pre>
<br />
<br />
SElib is used to call a DLL, passing in the reference to the buffer
<br />
<br />
<pre style="brush: js’;">SElib.dynamicLink("jddll.dll", "score", CDECL,
…
P_CHURN_SCORE,
R_CHURN_SCORE,
);
</pre>
<br />
<br />
The following C snippet, de-references the pointers, and modifies the data at the memory address that was allocated in the above eScript code.
<br />
<br />
<pre style="brush: js’;">#include <windows .h="">
_declspec(dllexport) int __cdecl
score (…
double *P_CHURN_SCORE,
double *R_CHURN_SCORE
{
*P_CHURN_SCORE = AGE + AVGCHECKBALANCE + AVGSAVINGSBALANCE;
*R_CHURN_SCORE = CHURN_SCORE + CONTACT_LENGTH + HOMEOWNER;
return(1);
}
</windows></pre>
<br />
<br />
<b>Clib vs eScript</b>
<br />
<br />
There is an obvious overlap between CLib and eScript functions, which causes some confusion on which is better to use. The recommendation from Siebel, is to use the eScript equivalent over Clib.
<br />
<br />
The CLib library is useful for OS level operations, and those scenarios where you need to operate at the memory level, but such usage is usually confined to edge cases, otherwise eScript provides a safer and more familiar playground for Siebel professionals.
<br />
<br />
<b>Conclusion</b>
<br />
<br />
Siebel designed eScript as a hybrid of ECMA Script and C, providing customers with the (not so well documented) ability to extend eScript beyond its natural abilities. Although everyday configurators may never need to touch the Clib libraries, use pre-process instructions, utilize reference operators or even call custom DLL's, but understanding these advanced features, and recognizing the C heritage provides insights for experienced developers, to maximize, and extend the product beyond its out of the box capabilities.
<br />
<br />
Finally, as for the great idea of renaming eScript, unfortunately the <a href="https://www.google.com.au/webhp?sourceid=chrome-instant&rlz=1C1CHMD_enAU563AU563&ion=1&espv=2&ie=UTF-8#q=c%20script">cScript</a> moniker is already taken (most notably by cscript.exe from MS), but you could also argue the same for 'eScript', which is claimed by these other software companies.
<br />
<br />
eScript - Eclipse scripting language<br />
<a href="http://wiki.eclipse.org/FAQ_What_is_eScript%3F">http://wiki.eclipse.org/FAQ_What_is_eScript%3F</a>
<br />
<br />
EScript - C++ Scripting language<br />
<a href="http://escript.berlios.de/pmwiki/pmwiki.php">http://escript.berlios.de/pmwiki/pmwiki.php</a>
<br />
<br />
Escript – Python programming tool<br />
<a href="https://launchpad.net/escript-finley/">https://launchpad.net/escript-finley/</a>
<br />
<br />
escript – Erlang scripting language<br />
<a href="http://www.erlang.org/doc/man/escript.html"> http://www.erlang.org/doc/man/escript.html</a>
<br />
<br />
eScript.api - This is the name of an Adobe plugin<br />
<a href="http://www.processlibrary.com/en/directory/files/escript/403646/">http://www.processlibrary.com/en/directory/files/escript/403646/</a>
<br />
<br />
As a consolation, we could designate eScripters who primarily use <i>Clib</i>, cScripters. I think this might catch on =)<br />
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com2tag:blogger.com,1999:blog-6992129293870658291.post-62488722474200387582014-06-12T20:44:00.000+10:002014-06-12T20:44:03.220+10:00Anonymous functions in Siebel<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">I was on a Project, that was performing an upgrade from Siebel 7 to
Siebel 8, and discovered parts of their Application was implemented using undocumented eScript features. The code was written by graduate web
developers, who used their trade to write ECMA compliant code, but
unfortunately some of these features were unsupported by Siebel 8.</span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />One
such feature was the usage of anonymous functions, which has the
following benefits.</span></span></span></div>
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />*
Provides locally scoped variables<br />* Can be used as a call
back function<br />* Allows better code readability<br />* Avoids extra
named reference on the current scope<br /><br />Unfortunately
anonymous functions, or even function expressions cause a reference
error in Siebel 8.</span></span></span><br />
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />> ReferenceError:'<somecontainerfunction>:-$753'
is not defined<br /><br />Siebel customers who need a viable
substitute have the option of using the Function
constructor, which is appropriately documented by Oracle here.<br /></somecontainerfunction></span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><a href="http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSReference189.html" target="_blank">http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSReference189.html</a><br /><br />Let’s
look at a real world scenario to see where this can come in handy.</span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />During
development, a Siebel developer might come across the need to
enumerate a PropertySet. The following code shows a basic
implementation of the enumerator function.</span></span></span><br />
<span style="font-family: arial, sans-serif; font-size: 12px;"><br />var propName = oPS.GetFirstProperty(), </span><span style="font-family: arial, sans-serif; font-size: 12px;">propValue</span><span style="font-family: arial, sans-serif; font-size: 12px;"> ="";</span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">while (propName != "") {</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;"> </span></span><span style="font-family: arial, sans-serif; font-size: 12px;">propValue</span><span style="font-family: arial, sans-serif;"><span style="font-size: 12px;"> = oPS.GetProperty(propName);<br /><br /></span></span><span style="font-family: arial, sans-serif; font-size: 12px;"> //### Do something with propName and propValue ###<br /></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;"> propName = oPS.GetNextProperty();</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">}</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;"><br /></span></span>
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">I propose that we create a utility for Siebel developers to easily loop over the properties of a single PropertySet level, without the above verbosity, using the following syntax.</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;"><br /></span></span>
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">1. [<PropertySet> ].psEach( </span></span><span style="font-family: arial, sans-serif; font-size: 12px;"><</span><span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">Callback> )</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">or</span></span><br />
<span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">2. util.psEach( </span></span><span style="font-family: arial, sans-serif; font-size: 12px;"><</span><span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">PropertySet>, </span></span><span style="font-family: arial, sans-serif; font-size: 12px;"><</span><span style="font-family: arial, sans-serif;"><span style="font-size: 12px;">Callback> )</span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />The
implementation of option 1 is outside the scope of this article, but
it can be easily built by customers who already have a familiar
construct in their Library.<br /><br />However option 2 should be a
little more familiar to customers who use script libraries in Siebel.
<b>util</b> is the name space, or the local reference to a name space from an eScript library. <b>psEach</b> is the logical method that performs
the enumeration.<br /><br />The following diagram shows, how we
should use the Function object in this context.<br /><br /></span></span></span></div>
<div style="margin-bottom: 0cm;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkMxqxFlo1GONzm7eLYK1wsqSu7T15IABG8aIyN_rg77mvbdbtivwoPGjUm7G7gyTgBebPtFh7ezpyKKIRWhXQzxzkuNfudqQPsz7lPd6uyME1CFGnxXOnB763cGbriZ1HygBnWPvRI3RV/s1600/the-harness-psnodeeach.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkMxqxFlo1GONzm7eLYK1wsqSu7T15IABG8aIyN_rg77mvbdbtivwoPGjUm7G7gyTgBebPtFh7ezpyKKIRWhXQzxzkuNfudqQPsz7lPd6uyME1CFGnxXOnB763cGbriZ1HygBnWPvRI3RV/s1600/the-harness-psnodeeach.png" height="51" width="400" /></a></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><insert image=""></insert></span></span></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">1. ‘Class_Util_PSNodeEach’
is the literal name for util.psEach.</span></span></span><br />
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">2. The
PropertySet that we wish to enumerate</span></span></span><br />
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">3. A
function object that will receive the Name, Value pair.</span></span></span><br />
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">4. This
function will receive two inputs n, v. This is optional, as the
arguments object can be used just as easily.</span></span></span><br />
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />The
following screenshot of <a href="http://www.impossiblesiebel.com/2013/07/the-harness.html">The Harness</a> shows the definition of
‘<b>Class_Util_PSNodeEach</b>’, the code that was used to set up the test case,
and the expected results.</span></span></span></div>
<div style="margin-bottom: 0cm;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUjNv87e5yS7YWasdFC6BDhw5dhM1ipoElMQLFECWwozWnkdFehOQHUcGDaXetMKcLycrBdtfrd74r7whsJ2bL4fwaKw0lfHS20phj9E4HtA5IHcpr9bOigbXiJcDWpDwmt0Pm8bKE6KWf/s1600/the-harness-new-function.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUjNv87e5yS7YWasdFC6BDhw5dhM1ipoElMQLFECWwozWnkdFehOQHUcGDaXetMKcLycrBdtfrd74r7whsJ2bL4fwaKw0lfHS20phj9E4HtA5IHcpr9bOigbXiJcDWpDwmt0Pm8bKE6KWf/s1600/the-harness-new-function.png" height="365" width="400" /></a></div>
</div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />Line
15. above shows where the magic happens, this API essentially
replaces 9 lines </span></span></span><span style="font-family: arial, sans-serif; font-size: 12px;">of code</span><span style="font-family: arial, sans-serif; font-size: 12px;"> </span><span style="font-family: arial, sans-serif; font-size: 9pt;">(x the number of times this construct is used in your Application) with 1 line.</span><br />
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />Just a friendly reminder that
this code has been simplified for illustration purposes, it is not is
not production ready or is it </span><span style="font-size: 12px;">optimized</span><span style="font-size: 9pt;"> to be used in the real world.<br /><br />> new Function("n,v", "log.info(n+' = ' +v " );<br /><br />The syntax above creates a new function on the fly, which expects an input of "n" and "v". It is invoked by line 5 in the screenshot above, and prints it out using a library method that outputs the result back to the UI. </span></span></span><br />
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br /></span></span></span>
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">This allows us to hide the clunky looping construct that is normally required to enumerate a PropertySet in eScript, and expose a much better API through <b>psEach.</b></span></span></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">Are
there any side effects?<br /><br /></span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">*
Code written inside the Function constructor is supplied as a
string, which has to be properly escaped</span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br />*
The function constructor will run in the scope of its instantiated
instance. This is normally the current Siebel event handler or
Business Service, or the code library where psEach lives, but it
could also be the instance of any object created by the new Operator.
What this all means is that, the callback function won’t inherit
the local scope of your object, and will not have access to your
local function’s variables unless they are passed in</span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;"><br /></span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">*
These functions won’t appear in your Siebel eScript object
explorer. This could also be an advantage.<br /><br /></span></span></span></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">In
context of the problem that we are trying to solve, the above list </span><span style="font-size: 12px;">doesn't</span><span style="font-size: 9pt;"> apply, but it should still be taken into consideration if you want to </span><span style="font-size: 12px;">utilize</span><span style="font-size: 9pt;"> this elsewhere in your Application, and please
check with your local eScript architect if you are unsure of the
impacts.</span></span></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><span style="font-size: 9pt;">Are
there any speed difference with either option? Once the function is
parsed, it will perform just as well as the function declaration. The
following test case shows that with our set up above, there are no
discernible speed advantage of using either method.<br /><br /><insert image=""></insert></span></span></span></div>
<div style="margin-bottom: 0cm;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEielWrQPk8gLGaMzYSBrPVUFMje0YOLFHG0K8Oc5cB2zLmshWJ4gIKTelFKCnRK_4ToEX-rPQ1VCsayax_0wa537aO2Q0G161xyKy_Vxu97J4DmKqVutlM43sAJx0ISOA31SGuk4SfmTvxc/s1600/the-harness-func-speedtest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEielWrQPk8gLGaMzYSBrPVUFMje0YOLFHG0K8Oc5cB2zLmshWJ4gIKTelFKCnRK_4ToEX-rPQ1VCsayax_0wa537aO2Q0G161xyKy_Vxu97J4DmKqVutlM43sAJx0ISOA31SGuk4SfmTvxc/s1600/the-harness-func-speedtest.png" height="400" width="390" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="color: black;"><span style="font-family: arial, sans-serif;"><br /><span style="font-size: 9pt;">The
Function constructor is possibly one of the most underused features
of eScript, but when used in the right way, it can provide your
project with the capability to </span><span style="font-size: 12px;">organize</span><span style="font-size: 9pt;">, and reduce the amount of
code that your developers have to write, test, and maintain. </span><br /><br /><span style="font-size: 9pt;">Further Reading Topics</span><br /><br /><span style="font-size: 9pt;">Function Constructor
JavaScript</span><br /><span style="font-size: 9pt;">Immediately Invoked Function Expressions (IIFE) or
</span><br /><span style="font-size: 9pt;">Self Executing Anonymous Functions (SEAF). </span></span></span></div>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com8tag:blogger.com,1999:blog-6992129293870658291.post-27392888565037572752014-06-06T20:57:00.000+10:002014-11-08T15:07:21.147+11:00The TestEvery once in a while, a developer decides to make a fix without unit testing and breaks the application. There are a variety of reasons why it occurs, it could be that the developer got too confident, maybe it hard to setup the test case, it could be due to inexperience, or it could be due to pressure to turn around the defect, and check it in.<br />
<br />
It could also be less sinister, maybe unit testing was performed, but the fix had other unintended impacts, or the unit test was not creative enough to produce errors, or worse still, the defect goes unnoticed until it is released into the wild.<br />
<br />
Unfortunately it happens, but can it be prevented?<br />
<br />
Imagine your Siebel developers could run a suite of automated test cases, to verify the sanity of the core application just before check in. This would provide your project with a good measure of quality assurance that the application isn't broken. How good the measure is, depends on your test coverage.<br />
<br />
Testing can be exhaustive, and take hours to regression test the Application. To make things more manageable, we can split it into two categories.<br />
<br />
1. Core application<br />
2. Business functionality<br />
<br />
2, can be covered by more comprehensive regression test methods, and are done post check in. Sometimes this is too late. The concept of ‘The Test’ is to focus on 1. Testing the core application, to verify that what’s being checked in, doesn't cause widespread damage to the application in the next migration.<br />
<br />
In the past, I've covered this topic in the following articles<br />
<br />
SiebUnit - an xUnit implementation<br />
<a href="http://www.impossiblesiebel.com/2012/02/siebunit-xunit-implementation.html">http://www.impossiblesiebel.com/2012/02/siebunit-xunit-implementation.html</a><br />
<br />
SiebUnit - Build Inventory<br />
<a href="http://www.impossiblesiebel.com/2012/02/siebunit-build-inventory.html">http://www.impossiblesiebel.com/2012/02/siebunit-build-inventory.html</a><br />
<br />
I've had a lot contact from various Siebel customers over the above articles, confirming that the tool meets a real world need.<br />
<br />
“The Test” is not as ambitious, its purpose is to be simple, effective and a lot easier to implement, but it’s not declarative. Writing code to test code, and maintain that extra code, isn't a deal breaker, what’s more important is that your developers have the confidence to make core changes, and your application is protected from serious defects.<br />
<br />
Like SiebUnit, the main requirement of ‘The Test’ is to have testable interfaces. Testable interfaces are API’s that can accept an input, produce an output, without any reliance on Siebel’s application context, and are predictable. Ideally it should also have as few dependencies as possible. <br />
<br />
In Siebel, these API’s take the following forms.<br />
<br />
Business Service<br />
Workflow<br />
Script Library<br />
eScript<br />
Browser/OUI Script<br />
<br />
To test the above interfaces, I propose we create a Test library using eScript (for testing server side APIs), it could sit inside your existing Script library if you have one. <br />
<br />
There should be an external method called “The Test”, this method could instantiate a new Test class, with a main entry point called “run”, that would run groups of test cases, each of these groups would contain 1 or more test cases. To facilitate the writing of clean test cases, I suggest we enforce a formal structure.<br />
<br />
The following code snippet shows an implementation of the above concept in Siebel.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRa9JOuvk06is4BuSZoCLt3E3fz8YcqtopDYWWcL9Q-A8hbc-poyRdk0KzNBL-2u1lxN7VzpcMgA8TEHmavdLCnocFQVpFFgFs93EOysNYbsf4Lp2Bci1kkkyvd-juhrW9J_RDELBNiU3/s1600/Test_case_general.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQRa9JOuvk06is4BuSZoCLt3E3fz8YcqtopDYWWcL9Q-A8hbc-poyRdk0KzNBL-2u1lxN7VzpcMgA8TEHmavdLCnocFQVpFFgFs93EOysNYbsf4Lp2Bci1kkkyvd-juhrW9J_RDELBNiU3/s1600/Test_case_general.png" height="152" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
1. Calls a script library function called parseINI that will be tested. The util namespace is used, and invokes parseINI, to return object representation of a configuration file</div>
<div class="separator" style="clear: both; text-align: left;">
2. assert is defined as a class function.</div>
<div class="separator" style="clear: both; text-align: left;">
3. The purpose of ‘assert ‘, is to determine if a test case has passed or not. The first argument passes the evaluated the condition to assert. </div>
<div class="separator" style="clear: both; text-align: left;">
4. The Output PropertySet is passed to assert for logging the result</div>
<div class="separator" style="clear: both; text-align: left;">
5. A description is provided to identify the test case.</div>
<div class="separator" style="clear: both; text-align: left;">
6. Test case helpers to minimize coding.</div>
<br />
Examples of helpers<br />
<br />
* Create a common complex hierarchy for PS manipulation<br />
* Invoke Siebel APIs without using setting up PropertySets<br />
* Invoke WF without the normal setup<br />
* Create a data randomizer to facilitate more creative test cases.<br />
<br />
<br />
The good news is that with a bit of organization, we can reduce the amount code that a developer has to write to test your APIs. I claim that these test cases are readable, are easily maintained, and require no effort to pick up, other than the inertia to change ones habits.<br />
<br />
Now that we have a proposed test case construct, we need to have an ability to report on the test results. Step 4 states this from a high level, but the report can be as simple as name value pairs on an Output PropertySet, or as complex as you need. The report should at the very least, display the number test cases that have passed and failed. This will allow the developer identify where the problem is, fix the issue, and re run The Test again to ensure that all expected test cases pass.<br />
<br />
Establishing your Test library a great first step, but acquiring it alone is not is actually not enough, the project has to foster the culture of writing test cases into developers, and factor the effort into the build estimates. The project also has to identify what is testable, and augment what is not testable. A script library is a good example of a testable interface, members of the audience who have the ABS framework on their projects, should be familiar with "The Test".<br />
<br />
It takes effort to write the test cases, as well as to maintain them going forward. To be conservative, your current unit testing estimates should be doubled when implementing automated test cases. This may sound a little daunting, so lets take a look a little example that demonstrates the ROI.<br />
<br />
Testing an email address validator<br />
<br />
You have a written a library function to test the validity of emails. The manual method of test this might be to launch the UI, and navigate to a view, where you repeated enter a series of bad, and good emails, to test the string. Lets say that takes you 5 minutes to perform, and writing automated test cases for the same scenario takes 10 minutes. Now imagine a defect was raised against your code, you would need to fix the defect, and spend another five minutes to re-validate the function to ensure you haven't broken something else. On the other hand, your automated test cases can be re run in an instant.<br />
<br />
The initial effort to write the test case, will be paid back in spades. Your application will require less re-development, and suffer less downtime as a result, your developers will have the confidence to make core changes, automated unit tests can be your unit test documentation, your application will be more robust, and my personal favorite, is that developers can write the unit test once, and run it multiple times.<br />
<br />
Once you have the right framework in place, and given enough experience (1-2 weeks), writing test cases actually saves more time than not writing them.<br />
<br />
The Test is simple to build, and can be taken as a quick win towards a larger goal, for ensuring a better quality product. However be warned that once you start writing automated test cases, you won't want to look back to manual testing.<br />
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-22777951873111419022013-12-03T21:31:00.000+11:002015-07-14T23:36:51.413+10:00The Harness Case StudyThe Harness started out as a humble 'App' to send and receive MQ messages on the thin client, but it has since grown to become an indispensable tool for Siebel development and testing. This was introduced to readers on a previous post titled <a href="http://www.impossiblesiebel.com/2013/07/the-harness.html">'The Harness'</a>
<br />
<br />
In case you missed it, here are some of its key features
<br />
<br />
* Simulate any Business Service from any screen with active context<br />
* Run eScript on the fly in any object manager<br />
* Construct & perform BC operations without scripting<br />
* Send/receive MQ messages<br />
* Base64 encode/decode, and previewing of Base 64 images<br />
* Regular regression tester with result highlighting<br />
* Generate random test data <br />
* On the fly XML conversion between Siebel formats, and passing as an input into a BS<br />
* Open UI API browser/console<br />
<br />
These features were built for the developers of a specific client, but if you like the idea of building such a tool for your own project, this article provides an approach for the new breed of Siebel/Web solution designers out there to follow.
<br />
<br />
<b>Architecture</b>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGp9bFY1E6HV9aB3KnatmLO07amGLbkYJPCJInqlmfDIPjdvTCBLX8OpqnRfVoYdumuooSDIL_rJdEOnggw_Izq4A7MuX0Dh26YDnyTiWAX9p_WIpctsIaSCfYwQ91m1r8N8AKIH9PD1g4/s1600/TheHarnessArchitecture.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGp9bFY1E6HV9aB3KnatmLO07amGLbkYJPCJInqlmfDIPjdvTCBLX8OpqnRfVoYdumuooSDIL_rJdEOnggw_Izq4A7MuX0Dh26YDnyTiWAX9p_WIpctsIaSCfYwQ91m1r8N8AKIH9PD1g4/s400/TheHarnessArchitecture.png" /></a>
<br />
<br />
The above diagram highlights the main components that make up The Harness. Each point will be discussed below.
<br />
<br />
1. The Harness UI<br />
<br />
Provides an interface allowing developers to interact with your Tool.
<br />
<br />
The UI was hand built using HTML, with jQuery for handling the interactions, and providing the animations.<br />
<br />
[Responsibilities] <br />
<br />
Provides pretty UI for the user<br />
Pretty prints ECMA Script/XML, displays tabular data<br />
Data entry<br />
<br />
<br />
2. The Harness Core<br />
<br />
The core logic (written in Javascript, with support from jQuery) responds to user actions, orchestrates the work needed to construct requests, execute actions and formats the response before being displayed to the user.
<br />
<br />
[Responsibilities] <br />
<br />
Interface with Storage bridge <br />
Interface with Siebel API through Proxy <br />
Interface with Server libraries through Proxy <br />
Convert between different data representations<br />
Constructs Request from data elements<br />
<br />
<br />
3. Proxy<br />
<br />
Communication between browser and server is managed through a custom proxy, which routes all browser commands to a common entry and exit point. The proxy communicates with the Siebel through a business service invocation, using PropertySets to transport data.
<br />
<br />
[Responsibilities] <br />
<br />
Interfaces with Siebel API<br />
Single point of communication between browser/server<br />
Encode/decode HTML entities<br />
Encodes/Decodes command from browser/server<br />
<br />
<br />
4. Local data store bridge<br />
<br />
The local data store bridge provides a high level API for interfacing with the available storage technologies on the browser. There are many 3rd Party storage libraries that provide this functionality, eg. LawnChair, jsStorage, PersistJS
<br />
<br />
[Responsibilities] <br />
<br />
Interface with lower level browser Storage API<br />
<br />
<br />
5. Third Party<br />
<br />
Third Party libraries are used for syntax highlighting, JS code editor, JSHint, animation<br />
<br />
[Responsibilities] <br />
<br />
Adds sugar to The Harness<br />
<br />
<br />
6. Local storage<br />
<br />
Local storage is medium for persisting data on the Client. This can be Web SQL, IndexedDB, HTML Storage, Cookies, depending on what is supported on the users browser. The APIs for these storage options are different, so we’ve used the local storage bridge above to abstract the browser implementation from our logic.
<br />
<br />
[Responsibilities] <br />
<br />
Persists client side preferences<br />
Stores historical requests<br />
Save to favourites<br />
<br />
<br />
7. Browser (Siebel) UI<br />
<br />
The Harness is linked to the Siebel UI. This means, we can get the active context of the current browser session, allowing us to implement a business service simulation interface that can work with <i>TheApplication().GetActiveBusObject()</i>. This also allows us to run browser script, or call Open UI’s new API.
<br />
<br />
[Responsibilities] <br />
<br />
Launches The Harness <br />
Interface with Siebel’s browser layer <br />
Interface with Siebel’s active context<br />
<br />
<br />
8. Server deployed components<br />
<br />
This consists of custom script libraries, JAR files, WFs, supporting Business Services, and SRF modifications.
<br />
<br />
[Responsibilities] <br />
<br />
Provide server support for our features<br />
<br />
<br />
<b>Challenges</b>
<br />
<br />
Working external to the Siebel repository, and outside the guidelines of classical Siebel development brings some new challenges.
<br />
<br />
This is the world of the new hybrid Siebel/Web developer, but the lessons learnt here, is also applicable for traditional developers.<br />
<br />
<b><i>Supportability, Maintainability, Persistence, Session Attachment, Access Rights, Deployment</i></b>
<br />
<br />
<b>Supportability</b>
<br />
<br />
When designing a solution, whether it be for Siebel, or for some other application, best practice dictates that we stick to the published supported interfaces.<br />
<br />
Undocumented features in Siebel can be an ambiguous bucket. <br />
<br />
There are a lot of ‘undocumented’ features in eScript as it is based on the ECMA specification. Siebel provides documentation for its eScript API, but not for all the ECMA scripts features, so projects need to make sound judgements on the use of these features, and have the in-house expertise on standby to support it.
<br />
<br />
However if you’ve discovered an undocumented user property, remember this isn’t part of any supportable standard. First consider the available alternatives, then choose to use it with caution, but have a contingency plan. User properties have faired quite well in upgrades compared to scripting alternatives.
<br />
<br />
However, if the solution depends on a hack, be prepared to lose that feature in a future upgrade. <br />
<br />
The Harness was built pre Open UI, and has lasted upgrades through 8.1.1.15, 8.1.1.10, 8.1.1.11.
<br />
<br />
<b> Maintainability </b>
<br />
<br />
Can your solution be easily extended without too much effort? Your design, should limit the points of configuration, utilise common libraries, and separate configuration from code, this will help with maintainability and extensibility. Spend the time to refactor your code at key stages of its development.
<br />
<br />
<b> Persistence </b>
<br />
<br />
Like user preferences in Siebel, the goal of persistence is to remember changes in the state of the browser, and personalize the experience.
<br />
<br />
As a testing tool, The Harness was built to remember inputs for named test cases, and historical test runs. As a development tool, The Harness had to remember previous actions for recall, review, and reruns.
<br />
<br />
Cookies may be the first consideration for Siebel veterans who have a side interest in web technologies, but there are better modern alternatives such as HTML storage, Web SQL, Indexed DB. Unfortunately, the implementation isn’t quite standard across browsers, so the solution to this is to use a storage bridge to abstract your interface from the capabilities of the individual browsers.
<br />
<br />
Keep in mind that these are cached on the clients hard disk, if there is a requirement to have persistence across different machines, then the naturall place for this is on the server. The Harness utilizes a further layer of abstraction on top of the 3rd Party library, allowing it to switch to a different API without costly changes.
<br />
<br />
<b>Session Attachment/Access Rights</b>
<br />
<br />
The Harness UI is built from an independent HTML file, and needs to be launched by a user’s action. Considered placements for this launch, can range from the Application menu, from a button on an admin screen, short cut key launch, or via a visibility based icon.
<br />
<br />
This leads to the question of how to secure the tool from unauthorised access. My mentor once told me, the best security is non-disclosure, if the users don’t know it’s there, they won’t be able to use it!. Although there is some truth to that, The Harness employs a more secure approach by providing access rights through a server side administration screen. <br />
<br />
<b>Deployment</b>
<br />
<br />
The Harness weighs in at more than 10Mbs, with server and client side artifacts. It was important to facilitate ease of installation, updates, and maintenance on the product.
<br />
<br />
The Siebel web server separates its resources into different locations for SCRIPTS, FILES, 3RDPARTY and IMAGES. Following this pattern makes sense, but it also makes it more error prone to deploy without a proper build process.
<br />
<br />
An ANT build process was implemented to facilitate deployment of external file resources.
<br />
<br />
<b>Conclusion</b>
<br />
<br />
Have your staff have been stuck troubleshooting why a piece of code runs differently in the users object manager, than the WF Object manager?. The Harness can dispatch a chunk of eScript to run on the Server, without costly compiles/deployment.<br />
<br />
In a diferent scenario, a developer might be wondering why an XML payload, when transformed into a Siebel Message doesn’t 'upsert'. With The Harness the developer can take the transformed message, or handcraft a modified version, and test out different message structures on the fly, and upsert it without touching tools.<br />
<br />
Siebel developers around the world have figured out ways to work smarter, and build competitive advantage through custom tools and processes. It’s in the DNA of every developer, hopefully these ideas inspires designers out there to take the next step to build unique solutions for your clients.<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com4tag:blogger.com,1999:blog-6992129293870658291.post-62430275654920882812013-11-08T22:02:00.001+11:002013-11-08T22:05:12.322+11:00Open UI: Close Popups on Escape KeyThe ESC key in many traditional applications, provides a convenience shortcut to stop, undo, or go back in the application. It enhances the usability of an application by allowing the user to navigate backwards quickly or work more effectively work with two hands.
<br/><br/>
This feature is also built into major modern browsers, with the ESC key allowing users to dismiss dialog boxes. This feature works on native browser dialogs such as the <i>alert</i>, <i>confirm</i> and <i>prompt</i> dialogs, as well as artificial dialogs, such as the new notification pane seen in Open UI.
<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0a-O_vfcEGwkd2TwtIsFacij9VTy40fb8NbvqgIB59ecG_m_FQbP4N7BFnTu9lI3I9kgtJP0cO10WceaKkenIqLvQpllwXRsG08wgCggJz-zTlLTTGXdfsdPjHqARYrhiYuqJse-kqROw/s1600/OUI_ESC_Notif_sum.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0a-O_vfcEGwkd2TwtIsFacij9VTy40fb8NbvqgIB59ecG_m_FQbP4N7BFnTu9lI3I9kgtJP0cO10WceaKkenIqLvQpllwXRsG08wgCggJz-zTlLTTGXdfsdPjHqARYrhiYuqJse-kqROw/s400/OUI_ESC_Notif_sum.png" /></a>
<br/><br/>
Right click on the Notification Pane, and inspect the source code behind this UI element. It will look something like this:
<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTrrQfXyBcYLMDG25v-IrlzjHsiM-BaHm5ZznXZx2PoF9KA0F6ihl1tZEDTOS6ceAi5Nmgj-K7lWIlfgJgI4nRYXNK70xATPT6YrPl-cKeyStGezvUhs74DWmZxLn4zCbKy2diMBQOC15/s1600/OUI_ESC_JQ_Dialog_Class.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTrrQfXyBcYLMDG25v-IrlzjHsiM-BaHm5ZznXZx2PoF9KA0F6ihl1tZEDTOS6ceAi5Nmgj-K7lWIlfgJgI4nRYXNK70xATPT6YrPl-cKeyStGezvUhs74DWmZxLn4zCbKy2diMBQOC15/s400/OUI_ESC_JQ_Dialog_Class.png" /></a>
<br/><br/>
The class attribute of the container gives it away as a jQuery dialog.
<br/><br/>
You may not know it, but you will be interacting with jQuery dialog boxes throughout Siebel Open UI. Just inspect the browser source for any MVG, Pick or any Popup applet in Open UI, and it will reveal the same class attributes as the Notification Pane. This tells us they are constructed using the same plugin, except these other 'dialogs' cannot be dismissed with the ESC key.
<br/><br/>
Lets see if we can imbue these other applets, with the ability for us to dismiss them using the ESC key.
<br/><br/>
This behaviour is controlled by the following code snippet
<br/><br/>
<pre class=’brush:js’>
$("[name=popup]").dialog({
position : "center",
modal : true,
autoOpen : false,
//This line disables the ability to dismiss dialogs using ESC
closeOnEscape : false
});
</pre>
<br/><br/>Log onto the Application, and select “Help > About View”, open the Query Assistant Applet, or choose any other popup applet, this will initialise the jQuery dialog. Press the ESC button, and at the moment, nothing will happen.
<br/><br/>
Press F12 on your browser to bring up the built-in debugger, and paste the code below.
<br/><br/>
<pre class=’brush:js’>
$("[name=popup]").dialog( "option", "closeOnEscape", true );
</pre>
<br/><br/>
Now with that same popup applet still open, press ESC, and watch that applet disappear. Any popup applet that is opened in the Application at this point also inherits this behaviour.
<br/><br/>
The above code will act the basis of our solution, but it only works if a popup has already been opened, so the most appropriate event is the first time a popup applet is displayed. This makes <i><a href=” http://docs.oracle.com/cd/E14004_01/books/config_open_ui/appendix_a_API15.html#wp1143136”>ShowUI</a></i> a good candidate, as we can detect when a popup is open, and set the dialog option.
<br/><br/>
For testing purposes you can put the following code the <i>ShowUI</i> handler of any popup renderer.
<br/><br/>
<pre class=’brush:js’>
if (!$( "[name=popup]" ).dialog( "option", "closeOnEscape" ) ){
$("[name=popup]").dialog( "option", "closeOnEscape", true );
}
</pre>
<br/><br/>
The above code detects if the <i>closeOnEscape</i> option of the jQuery dialog is disabled, and proceeds to enable it. It works even if the first popup applet is opened, and has been initialised to <i>false</i>.
<br/><br/>
The above code only works for a particular applet, and any subsequent popup applets opened from that point onwards, so a better approach is to put the code under the global ShowUI handler, which will enable the feature for any popup that is opened, however we only want to run it once.
<br/><br/>
To achieve this, we can use the technique below, which re-writes the logic to cut out the if statement after the first time the dialog option is set.
<br/><br/>
Note: This code is provided for educational purposes only, and should not be used in production environments.
<pre class='brush:js'>
function Global_PreShowUI(){
//Call the usual ShowUI function
Global_PreShowUI_Rewrite();
//Perform popup dialog check
if (!$( "[name=popup]" ).dialog( "option", "closeOnEscape" ) ){
$("[name=popup]").dialog( "option", "closeOnEscape", true );
//Rewrite the current function after the first popup has been detected
Global_PreShowUI=Global_PreShowUI_Rewrite;
}
}
function Global_PreShowUI_Rewrite(){
//Show UI code goes here
}
</pre>
<br/><br/>
The line below shows where the application logic is being re-written.
<br/><br/>
<pre class='brush:js'>
Global_PreShowUI=Global_PreShowUI_Rewrite;
</pre>
<br/><br/>
The subsequent time <i>Global_PreShowUI</i> is fired, it will go straight to the real <i>Global_PreShowUI_Real</i> handler, which means our conditional test is only evaluated once. Neat!
<br/><br/>
Usability has always been thrown in the too hard basket, and although browser script techniques have been available to improve usability in Siebel HI, it has only been attempted by the brave.
<br/><br/>
The ESC key is already used in Siebel to undo query, undo record, and dismiss dialogs. Open UI now provides the option for customers to extend this feature to all Siebel popup applets.
<br/><br/>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-58457223266614519882013-11-07T22:18:00.000+11:002013-11-12T21:52:44.238+11:00Open UI: SiebelJS.Log & The Stack
<b>Introduction</b><br/><br/>
<i>SiebelJS.Log</i> allows the developer to debug the application by writing to the browser console. This has been provided since 8.1.1.9.
<br/><br/>
Most modern browsers have <i>console.log</i> which performs the same function, except <i>console.log</i> causes an error in IE if the developer toolbar has not already been opened. <i>SiebelJS.Log</i> avoids this problem by first checking if the console object is available, before calling the log method.
<br/><br/>
<i>SiebelJS.Log</i> is better for this reason.
<br/><br/>
<b>SiebelJS.Log in 8.1.1.11</b>
<br/><br/>
In 8.1.1.11 Oracle changed the way <i>SiebelJS.Log</i> works.
<br/><br/>
<i>SiebelJS.Log</i> no longer supports a string argument, but rather an Error object. This also means all previous log statements from 8.1.1.10 will be ignored silently.
<br/><br/>
Update: The above behaviour affects the only the 8.1.1.11 sample application. SiebelJS.Log has been redefined in 8.1.1.11 to support an Error object, but passing in a String will still log to the console.
Usage
<br/>
<pre class=’brush:js’>
TestPRList.prototype.ShowUI = function(){
hello_a();
};
function hello_a(){
hello_b()
};
function hello_b(){
hello_c()
};
function hello_c(){
SiebelJS.Log( new Error('Error occurred here')) ;
};
</pre>
<br/><br/>
Result
<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeo6OJPhzm7NIK-ElRlr6MgdurgLwlIZ8wjvjVcxtoP2hZA5WrRpxG7cIJhbVZyq8dHeT4icWfxCvB4gyj-J9K_hwaR0O0zEJK-APgR4AfRkcpAXXKLmZKqEuKiP0y-BArWD5g7Ql5wS0/s1600/SiebelJS_Trace.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeo6OJPhzm7NIK-ElRlr6MgdurgLwlIZ8wjvjVcxtoP2hZA5WrRpxG7cIJhbVZyq8dHeT4icWfxCvB4gyj-J9K_hwaR0O0zEJK-APgR4AfRkcpAXXKLmZKqEuKiP0y-BArWD5g7Ql5wS0/s400/SiebelJS_Trace.png" /></a>
<br/><br/>
Notice that it produces an error message with a stack trace.
<br/><br/>
If you don't like the stack trace produced by <i>SiebelJS.Log</i>, you can call <i>SiebelJS.Trace</i> or <i>console.trace</i> directly to produce a stack trace without the error message.
<br/><br/>
Just substitute <i>SiebeJS.Log</i> with <i>console.trace</i> in the above example. This results in a much cleaner output as can be seen below.
<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2txh9oGIydQ3wKJf2aOjMQfpj0ja0uD9eP7gyKTwrRK23m7kXpodAjVQG4HciPXg5TW9rQfL6dmU7Lkw-eTxSte04utKL1-PBOXoQKPFNa3kGBs3hg1syyvgiLRDsyC9I77m8n_pxwMAR/s1600/SiebelJS_Trace2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2txh9oGIydQ3wKJf2aOjMQfpj0ja0uD9eP7gyKTwrRK23m7kXpodAjVQG4HciPXg5TW9rQfL6dmU7Lkw-eTxSte04utKL1-PBOXoQKPFNa3kGBs3hg1syyvgiLRDsyC9I77m8n_pxwMAR/s400/SiebelJS_Trace2.png" /></a>
<br/><br/>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/console.trace">console.trace</a> is supported in Chrome, Firefox, and Opera.<br/><br/>
<b>Conclusion</b><br/><br/>
Although there has been no official documentation page on the <i>SiebelJS</i> class and its available methods, it has been used in Oracle Bookshelf alongside usage examples of other methods, and as such, can be considered to be implicitly documented.
<br/><br/>
For better or for worse <i>SiebelJS.Log</i> has been redefined to be used as an error logger. Open UI customers that need a method for logging, are better off creating a wrapper around <i>console.log</i>, and put it in a client side library (if you haven't already done so).
<br/><br/>
8.1.1.11 brings many changes, including unspecified changes to the browser API. Customers that are upgrading from 8.1.1.10, will find that customizations don't port over without some rework.
<br/><br/>
The temptation to use undocumented methods is ever present, because the source code is more readable than the documentation. This serves as a good reminder for us to avoid using undocumented methods, or at least have a good mitigation strategy if you do use them.
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-55890553055581838382013-10-30T21:24:00.000+11:002013-10-30T21:24:17.339+11:00eScript: The Siebel StackDoes 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.
<br />
<br />
Respected ex Siebel engineer Mike M Lin, wrote an article on <a href="http://siebelhacker.blogspot.com.au/2009/01/getting-call-stack-from-escript.html">Getting the Call Stack from eScript</a>. In that article, he raises a Siebel exception, and scrapes the error <i>message</i> property to get the call stack. Unfortunately in Siebel 8, Siebel has removed the stack trace information from the error <i>message</i> property when using <b>TheApplication().RaiseErrorText</b>. Siebel has also blocked the ability to enumerate the error object, so the same test case can’t be performed.
<br />
<br />
According to <a href="http://www.blogger.com/%E2%80%9Dhttp://docs.oracle.com/cd/E16348_01/books/eScript/methods_reference129.html%E2%80%9C">bookshelf</a>, when an operation fails, Siebel generates an <i>Exception Object</i>. The exception is documented with two properties: <i>errCode</i>, and <i>errText</i>
<br />
<br />
I’ve taken the Siebel example, added some log statements, and put it through <a href="http://www.impossiblesiebel.com/2013/07/the-harness.html">The Harness</a>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUvaKFCG8MCfHby4MZ9ww7DwXfH1TUv2PkViz1NvHN0KHfCZdNBhaCHoYBwU2Jsr5GLbWAW4XtorajkHhj4hkIrUaD2IcNyPXPXItbpGb-eQKS86dnlJJlDCFa-sNB9SnTuUryXmRp6qlJ/s1600/ErrStack_Exception_Bookshelf_Test_example_result.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUvaKFCG8MCfHby4MZ9ww7DwXfH1TUv2PkViz1NvHN0KHfCZdNBhaCHoYBwU2Jsr5GLbWAW4XtorajkHhj4hkIrUaD2IcNyPXPXItbpGb-eQKS86dnlJJlDCFa-sNB9SnTuUryXmRp6qlJ/s400/ErrStack_Exception_Bookshelf_Test_example_result.png" /></a>
<br />
<br />
We verify that the error is indeed an instance of the <i>Exception Object</i>, and that the Siebel example works.
<br />
<br />
Next I modify the example to include the two properties that Mike M Lin, identified as part of his test case:
<br />
<br />
<i>name, message</i>.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU3ADhMJsausynNLWRACavd9K0ipkOB6H5KxkA6VHNxhaIVSi97h7__2QuXbEnuiK8_wPgs-1ppiwldwfR7E9NlRJ-jxdbT4SmLtGRfDzgPcafxLSn_XiBldUIbmmcpSzGvjffa_waLcKi/s1600/ErrStack_Exception_Bookshelf_Test_example_result2.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU3ADhMJsausynNLWRACavd9K0ipkOB6H5KxkA6VHNxhaIVSi97h7__2QuXbEnuiK8_wPgs-1ppiwldwfR7E9NlRJ-jxdbT4SmLtGRfDzgPcafxLSn_XiBldUIbmmcpSzGvjffa_waLcKi/s400/ErrStack_Exception_Bookshelf_Test_example_result2.png" /></a>
<br />
<br />
<i>Name</i> turns up a blank, and <i>message</i> stores the same value as <i>errText</i>. There is no stack trace in sight, so I try the same test case with <i>TheApplication().RaiseErrorText()</i>, as Mike did, but unfortunately this also produces no stack trace.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5q108H9NKI4-NC7hQxSunxBDq03wWklC3TP-6835MM0Y4vqe7k0q9My6XIEA_ltJnrCzdkm96wUgy3iYEQv2ScJAhMBUFvg0bBmiEZM2ezDRfqATnDobBsaOdJM67_Uj08tH75MwWvHC8/s1600/ErrStack_Exception_Bookshelf_Test_example_result3.png" imageanchor="1"><br /><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5q108H9NKI4-NC7hQxSunxBDq03wWklC3TP-6835MM0Y4vqe7k0q9My6XIEA_ltJnrCzdkm96wUgy3iYEQv2ScJAhMBUFvg0bBmiEZM2ezDRfqATnDobBsaOdJM67_Uj08tH75MwWvHC8/s400/ErrStack_Exception_Bookshelf_Test_example_result3.png" /></a>
<br />
<br />
<b>Producing the Stack Trace</b>
<br />
<br />
We can conclude that the Siebel Exception object no longer produces a stack trace, but <i>Siebel Exception objects</i> aren’t the only types of Error objects that are created in eScript. According to the <a ecma-262="" href="http://www.blogger.com/%E2%80%9D" http:="" www.ecma-international.org="">ECMA specifications</a>, which Siebel eScript is based on, there are other types of errors that can be thrown.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kZNMfb8Sd3MJLh2v61YvKOnFiVBAbWbTBHfcRLmqgkttkZUYbJ67hF1uH8F6PvteZJD57fqdGaH58HldVIFMjjXODIRtcDOInhyz4GvvFOwrVvG4tka17_izout5EhKUTO_FhTRgxt48/s1600/ErrStack_ECMA_Errors.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-kZNMfb8Sd3MJLh2v61YvKOnFiVBAbWbTBHfcRLmqgkttkZUYbJ67hF1uH8F6PvteZJD57fqdGaH58HldVIFMjjXODIRtcDOInhyz4GvvFOwrVvG4tka17_izout5EhKUTO_FhTRgxt48/s400/ErrStack_ECMA_Errors.png" /></a>
<br />
<br />
In the above example I’ve created a <i>Reference Error</i>, which reveals that the Stack trace is accessible with other error objects within Siebel.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUfQqhrifzf0D0xW2H1Z6CX4eu79T0YI3ZO5N6e1fjVYiLcXBrw1a0eVJ67LPVAsd4XluhQ19-EefckMLXIgDM0wcyzusR1GrUaMmi1A5awWR3vvEoYAZKWJbYuNXKRlIKN8zwNqo7puEI/s1600/ErrStack_Exception_StackTrace_result1.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUfQqhrifzf0D0xW2H1Z6CX4eu79T0YI3ZO5N6e1fjVYiLcXBrw1a0eVJ67LPVAsd4XluhQ19-EefckMLXIgDM0wcyzusR1GrUaMmi1A5awWR3vvEoYAZKWJbYuNXKRlIKN8zwNqo7puEI/s400/ErrStack_Exception_StackTrace_result1.png" /></a>
<br />
<br />
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.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvs2QM1bRWFEbyfK3OM0WQWf0Gm1QdcVbukTEbTZI57EBCYwy5WkBLI-ltBXlQlTMB2HutSk5GZBywRQGdU8F3MIBMw_A7plz4LbEc1b_QgrV5Sm0mOpDymVLiJrlcqpy6i5AoweWrHZmg/s1600/ErrStack_Exception_StackTrace_result2.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvs2QM1bRWFEbyfK3OM0WQWf0Gm1QdcVbukTEbTZI57EBCYwy5WkBLI-ltBXlQlTMB2HutSk5GZBywRQGdU8F3MIBMw_A7plz4LbEc1b_QgrV5Sm0mOpDymVLiJrlcqpy6i5AoweWrHZmg/s400/ErrStack_Exception_StackTrace_result2.png" /></a>
<br />
<br />
<b>Getting The Current Function Name </b>
<br />
<br />
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.
<br />
<br />
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.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7U60R2eyaEKxKnTrCBGyMfrviI89wUqdp6246vwXR6psDp8xcR79V1DOnLOYYISAHQgyquzrbBgO5rDRmxKjAFHVMh_J_awBndebMFDuL-eUHUV4aKcyI9y2PfI8hSDsonX189Hv9uh_d/s1600/ErrStack_GetFn_name.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7U60R2eyaEKxKnTrCBGyMfrviI89wUqdp6246vwXR6psDp8xcR79V1DOnLOYYISAHQgyquzrbBgO5rDRmxKjAFHVMh_J_awBndebMFDuL-eUHUV4aKcyI9y2PfI8hSDsonX189Hv9uh_d/s400/ErrStack_GetFn_name.png" /></a>
<br />
<br />
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.
<br />
<br />
<b>Error Object On Steroids</b>
<br />
<br />
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.
<br />
<br />
The concept of throwing a custom error object has been discussed before in <a href="http://www.impossiblesiebel.com/2009/11/abs-framework-logging-tracing-module.html">ABS Framework - Logging & Tracing Module</a>. 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.
<br />
<br />
It can be boiled down to the following steps.
<br />
<br />
1. Throw an error<br />
2. Check that the error is not an instance of our custom error <br />
3. Cause a stack trace using the method described above<br />
4. Scrape the relevant stack trace information, and ignore the dummy error message<br />
5. Scrape the error function name from the stack trace, also described above<br />
6. Create an instance of custom error with the above data<br />
7. Insert the original error from the real error object into the custom error object<br />
8. Re-throw the custom error <br />
9. At your root function check for the custom error, and log the stack trace, error information<br />
<br />
<br />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.
<br />
<br />
<b>Logger Concept</b>
<br />
<br />
Another complimentary method is to implement a custom script logger. This was also introduced to readers, when we visited the <a href="http://www.impossiblesiebel.com/2009/11/abs-framework-logging-tracing-module.html">ABS framework logging capability</a>. For a real life example of a logger, Siebel master Mik has kindly shared his design <a href="http://thesiebelscholar.blogspot.com.au/2010/05/escript-framework-logging.html">here</a>.
<br />
<br />
A sample logger template looks like this.
<br />
<br />
<pre class="”brush:js”">
function MyFunction (){
try{
log.begin("MyFunction");//hard coded function name
}catch(e){
log.error(e);
}finally{
log.end();}
}
</pre>
<br />
<br />
Every function would contain the above template, in which a custom logger is called with 3 main methods.
<br />
<br />
<b>log.begin</b> - Pushes a string of the current function name onto a custom stack<br/>
<b>log.end</b> - Pops the last function from the stack.<br/>
<b>log.error</b> - Logs the error<br/><br/>
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.
<br />
<br />
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 <b>log.begin</b>, and also consistently calling <b>log.end</b>.
<br />
<br />
<b>Conclusion </b>
<br />
<br />
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.
<br />
<br />
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.
<br />
<br />
Credits goes out to <a href="http://siebelhacker.blogspot.com.au/">Mike M. Lin</a> for providing the seeds for this article, <a href="http://thesiebelscholar.blogspot.com.au/">Mik Branchaud</a> for sharing his logger design, and Mr ABS for sharing his wisdom on error handling in the ABS framework.
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com5tag:blogger.com,1999:blog-6992129293870658291.post-19001574027494642602013-10-28T20:38:00.000+11:002015-05-22T23:23:00.532+10:00Open UI: Build Process<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv69MlOS7a-nOO5KrY9FALSUV0yD5HewzjB70sRiAMyUCKQ23WKPS82_oGaJ5ASS2YuXDsYuYqdAOFktvCiQIrGyFYd_Iuz5FV-h13RVrXRd38bnIASZjMpq3oatODmz-N0_xwSxtUf8ET/s1600/build+procss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv69MlOS7a-nOO5KrY9FALSUV0yD5HewzjB70sRiAMyUCKQ23WKPS82_oGaJ5ASS2YuXDsYuYqdAOFktvCiQIrGyFYd_Iuz5FV-h13RVrXRd38bnIASZjMpq3oatODmz-N0_xwSxtUf8ET/s640/build+procss.png" width="640" /></a></div>
<b><br />Introduction</b><br />
<br />
Siebel projects that are crossing over to Open UI, will soon realise the immediate need to implement standards around the development and deployment of the external resources in Open UI. Unlike traditional Siebel development, where source code is checked into a database and compiled into a SRF with a proprietary IDE, Open UI is based on text files that can be edited using Notepad.
<br />
<br />
Managing external files is not new to Siebel development, but it has never been mainstream, and the processes for managing these resources are not as mature on Siebel projects. This article is aimed at Siebel development managers looking to incorporate best practice from file based development environments, and integrating them with Open UI.
<br />
<br />
<b>Traditional Vs Modern Siebel Development</b><br />
<br />
A traditional Siebel development cycle involves the developer checking out and locking a project/object, the developer performs the modification, and checks it back in. The Siebel repository stores the source code, which must be compiled into SRF.<br /><br />Parallel development can be achieved by following the above process with a second repository, and managing the code promotion through a separate environment path. Eventually when those code bases needs to be merged, objects are moved between repositories through exporting and importing SIFs. Siebel provides a decent merge tool for configuration changes, but merging script is always a risky affair, due to the inability to perform a line by line merge.<br />
<br />
With Open UI development, developers have to switch from working with a database base repository to a file based repository. This file based repository is similiar to the Siebel repository that it stores the single source of truth for a particular release. Parallel projects can also be supported in a similiar manner, by establishing a separate container.<br />
<br />
Open UI development is very much like web development, files can be edited freely in your code editor of choice, the application can be easily debugged from any browser, and you have the flexibility to pick and choose your add-on web technologies. There is no longer a dependency on the Siebel way to build your application.
<br />
<br />
<b>Building your Application</b><br />
<br />
Do you use XSLTs, client side business services, custom images/JS/CSS, customized web templates? Then you need a build process. A build process allows projects to automate the production of artefacts for deployment with the following advantages
<br />
<br />
* Resources are deployed in a consistent manner
<br />
* Automated quality checks<br />
* Files are optimised for Production<br />
* Integration with Source Control
<br />
* Automated unit testing
<br />
<br />
To achieve the above tasks, we’ll need to establish the build process, procure the required toolset, and develop the necessary automation.
<br />
<br />
<b>Establishing a Process</b><br />
<br />
Projects need a formal strategy to manage the migration of files from source to deployment. Fundamentally this process should address how files are tracked, changed, merged and deployed, across multiple parallel development streams. This shouldn’t be new territory, so projects don’t have to go shopping for a new process, unless it is broken. Existing HI file deployment processes can be carried over, and augmented to incorporate the some of the best practices from modern web development.
<br />
<br />
* Integrated Source control
<br />
* Continuous Integration
<br />
* Automated test cases
<br />
<br />
<b>SCM (Source Control) </b><br />
<br />
The concept of building an application requires that we have a source. For traditional Siebel development, this source is the Siebel repository, in Open UI, the source should also be in a repository, but it is more likely to be a file repository rather than a database repository.
<br />
<br />
There are many solutions in the market that offer Software Configuration Management (SCM), but it is up to each project to choose the appropriate solution for their needs. The most obvious place to look is within your own organization to discover what SCM software is available, and used by other IT sections. This allows you to take advantage of the licensing agreements, and leverage the existing support arrangements that are already in place. Open source/free SCM sounds great, but it is risky to introduce it into an Enterprise, unless you have the expertise to maintain/support it yourself, otherwise prepare to negotiate for the support arrangements.
<br />
<br />
<b>Build Automation</b><br />
<br />
Automation tools allow projects to enforce a standard build process to a set of source files, create build packages and deploy it into its destination. Many projects schedule the automatic compilation of the SRF, generating browser scripts, and deployment of the SRF into development environments overnight. The same process could also be extended to deploy Open UI resources into the same development environment.<br />
<br />
Here are some examples of automation that can be applied to Open UI resources before deployment
<br />
<br />
* Add standard headers such as revision, organization details, release information, disclaimers to all files
<br />
* Strip comments from files
<br />
* Compress JS/CSS files through minification
<br />
* QA JS files with JSHint/JSLint
<br />
* Consolidate common JS Files to reduce HTTP requests
<br />
* Extract metadata from JS files, and produce documentation
<br />* Run unit test scripts<br />
<br />
Are you using a build process for HI? The same principles can be used in HI for other external resources.
<br />
<br />
Here are some ideas
<br />
<br />
* Automatically turn off XSLT indenting
<br />
* Generating XSLT documentation
<br />
* Extracting eScript from the repository and validating it
<br />
* Run interface test cases
<br />
<br />
<b>Code Editors</b><br />
<br />
While Notepad and other standalone editors are sufficient, it is recommended that you choose an editor that has the capability to detect JS language errors, integrate with your SCM, and automation tools.
<br />
<br />
Siebel Tools has this capability built in to an extent, but in Open UI, if you miss a closing bracket, and it is loaded via a common file, your application could fail silently, and pin pointing it to its exact source might not be fun. Code editors can perform the role of QA, by ensuring that your code is free from syntax errors before it is run against more stringent QA checks by programs like JSHint/JSLint
<br />
<br />
<b>Automated Test Cases</b><br />
<br />
Automated test cases are used as part of Continuous Integration to ensure that changes from multiple developers, work coherently and doesn’t break the application. The challenge is that developing automated test cases for the UI isn’t easy, at least not for traditional HI UIs. Open UI promises to be open, and exposes a new set of APIs for browser automation tools to interact with.
<br />
<br />
Until Oracle provides an Open UI automation client (for developers), conceptually, a project could develop their own Open UI automation testing, using a combination of the following tools
<br />
<br />
* Selenium
<br />
* Watir
<br />
* Ruby
<br />
* Custom JS OUI automation API
<br />
<br />
Selenium provides the browser automation, Watir is a ruby library that provides a nice abstraction onto of Selenium, and a custom JS interface provides the API bridge between Ruby, and the Open UI client.
<br />
<br />
<b>Toolchain</b><br />
<br />
Your build process will be dependent on the tools that’s supported by your organisation. The best tools for the job, are dependent on a variety of factors, like cost, availability, familiarity, features, and support. There isn’t a standard set of tools for everyone, however the main tools in your arsenal should be the IDE, SCM, and Automation tools
<br />
<br />
* <a href="http://en.wikipedia.org/wiki/Source_code_editor">List of source code editors</a>
<br />
* <a href="http://en.wikipedia.org/wiki/List_of_build_automation_software">List of build automation software</a>
<br />
* <a href="http://en.wikipedia.org/wiki/List_of_revision_control_software">List of SCM software</a>
<br />
<br />
Other tools to investigate
<br />
<br />
* JS minification
<br />
* JS/CSS consolidation
<br />
* JSHint/JSLint
<br />
* JS Documentation
<br />
<br />
<b>Conclusion</b>
<br />
<br />
Establishing a build process isn’t something that is restricted to large teams, it just important to have this process in place for a single developer working offline. There are times when you need to blow away an environment and rebuild from source control, or you need to rebase to a completely new project. Having source code control becomes critical for working in Open UI especially in large teams, so gone are the days where it is acceptable for developers to modify files directly on the web server.<br />
<br />
A build process can ensure that your application remains stable throughout the iterative development process, or alternatively without one, your project can become a cowboy arena, where developers go in, make adhoc changes, send off different file revisions for deployment via emails, and break the application at every deploy. The choice is pretty clear.
<br />
<br />
<b>Further reading</b>
<br />
<br />
* <a href="http://whyshouldiuse.com/source-control">Why use source control</a>
<br />
* <a href="http://addyosmani.com/blog/client-side-build-process/">Setting up a JS Build Process</a>
<br />
* <a href="http://siebel-ci.blogspot.de/">Siebel Continuous Integration Setup</a>
<br />
* <a href="http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging">Branching, Merging concepts with Git</a>
<br />
<br />
Some customers will have more mature processes than others, so what build tools are you using in your project?
<br />
<br />
To kick this off, here’s what works for me
<br />
<br />
* ANT (Build automation)
<br />
* ClearCase (SCM)
<br />
* Eclipse (IDE) + ClearCase Plugin
<br />* Sublime (IDE)<br />
* Eclipse JSHint integration via RhinoJS
<br />
* YUI Compressor (JS minification)
<br />
* + Selenium & Ruby for some UI automation fun
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com1tag:blogger.com,1999:blog-6992129293870658291.post-71508779257625921472013-09-20T20:53:00.001+10:002013-09-20T20:53:23.737+10:00The State of Siebel: Report and SurveyIf you weren't able to follow Bruce Daley's webinar "Where Do You Stand with Siebel" yesterday, here is a short wrap-up:<br>
<br>
Oracle Siebel CRM is a mature application showing both continued robustness and signs of age. With Oracle sending mixed messages about the product’s future, Bruce Daley, VP at Constellation Research has published a report which helps Oracle Siebel customers understand the real position Siebel technology holds in the market, why the conventional wisdom about the product is often wrong, and what trends are driving misconceptions in the market. It also offers pragmatic advice for taking Siebel implementations in different directions and how associated careers will be impacted.<br>
<br>
You can <a href="http://www.constellationr.com/content/where-do-you-stand-siebel-webinar-wrapup" target="_blank">view the replay and download the slides here</a>.<br>
<br>
You can <a href="http://www.riministreet.com/stateofsiebel" target="_blank">download the report with compliments of Rimini Street here</a>.<br>
<br>
<b>State of Siebel 2013 Survey</b><br>
<br>
Along with the report, Constellation Research and the Siebel Essentials blog are conducting a <a href="http://surveymonkey.com/s/2013siebelsurvey" target="_blank">survey</a> to feel the pulse of the Siebel community. If you are involved in a Siebel CRM project, please take some minutes to fill in the <a href="http://surveymonkey.com/s/2013siebelsurvey" target="_blank">survey form</a>.<br>
<br>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5xpal2CJ8tSO2B_xAgfPM6CR0isFAZT8mdrXvL_RC2sRprjfjlh6xwRBQGlmjCMio9sUWZOhpjN4EcEANl_cpunvdmMTRU9MUXqG4xrcMA0iRi-UpbfSgKptpohU9IEKxe-uxh-HfmUje/s1600/state-of-siebel-2013-survey-1.png" imageanchor="1"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5xpal2CJ8tSO2B_xAgfPM6CR0isFAZT8mdrXvL_RC2sRprjfjlh6xwRBQGlmjCMio9sUWZOhpjN4EcEANl_cpunvdmMTRU9MUXqG4xrcMA0iRi-UpbfSgKptpohU9IEKxe-uxh-HfmUje/s320/state-of-siebel-2013-survey-1.png" height="196" border="0" width="200"></a></div>
<br>
<br>
<a href="http://surveymonkey.com/s/2013siebelsurvey" target="_blank">Click here to access the survey</a>.<br>Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-69616228971015246372013-09-08T18:54:00.000+10:002013-09-08T18:54:03.672+10:00Constellation Research to Host Webinar on Where You Stand with Siebel<i>This free 45 minute webinar </i><i><span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;">will discuss what different directions Oracle Siebel professionals can take their Siebel implementation and their careers.</span></i>
<br />
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<i><span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;"><br /></span></i></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
Who: J. Bruce Daley, Vice President and Principal Analyst Constellation Research</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
What: Webinar: "Where Do You Stand With Siebel”<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;"></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
When: Wednesday, <b>September 18</b>, 2013 at<span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;"> </span>9:30 a.m. US Pacific time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
How: <a href="https://www3.gotomeeting.com/register/578393734" style="color: #1155cc;" target="_blank">https://www3.gotomeeting.com/<wbr></wbr>register/578393734</a><span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;"></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;"><br /></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;">Constellation Research, Inc., the award-winning research and advisory firm focused on disruptive technologies is offering a free 45 minute webinar to introduce a new analyst, J. Bruce Daley, in one of his primary research areas - the standing, enhancement, and conversion of legacy enterprise class software technology.</span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;"><br /></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;">His topic will be the different directions Oracle Siebel customers, partners, and consultants can take their Siebel implementation and their careers.</span> This year marks the 20<sup>th</sup> anniversary of Siebel technology and as<span style="font-family: Tahoma, sans-serif; font-size: 10pt; line-height: 13px;"> a mature application it shows signs of both robustness and age. With Oracle sending mixed messages about the product’s future, this webinar helps people making a living with Siebel determine exactly where they stand.<br /><br /></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
“Clearly Siebel technology is not dead and plays an important role in the IT infrastructure of many of our clients” noted R “Ray” Wang, CEO of Constellation Research. “Figuring out exactly where Siebel fits into the mix is challenging. We are excited that Bruce will bring his wealth of understand and experience to helping Siebel customers meet this challenge. ”</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
Daley was, for many years, the publisher of the Siebel Observer, the largest publication covering the CRM pioneer. Later he <span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;">co-founded a boutique advisory services firm that brokered the sale of system integrator Blue Hammock Inc. to GCI International (now called Collabera) and conducted over 250 consultations with mutual funds, hedge funds, and private equity funds. Widely quoted in The Wall Street Journal, The New York Times, The Financial Times, Daley also founded the Enterprise Software Summit.<br /><br /></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;">His first research paper for Constellation: “<b>Seeing the Good, the Bad, and the Ugly in Legacy Applications</b>: <i>How to Attack or Defend an Installed Base by Understanding How to Qualify the Success of a Legacy Applications </i>was published this week. This original research helps sales representatives and sales management determine how likely a legacy implementation is to be converted so they can qualify opportunities and threats more quickly. The report is available for purchase at <a href="http://www.constellationr.com/" style="color: #1155cc;" target="_blank">http://www.constellationr.com/</a></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;"><br /></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;">His second research paper “<b>The State of Siebel in the 2013 Market: </b><i>Different Strategies for Moving Siebel Implementations Forward and Assessing Career Risk</i><b> </b>will be published next week. This research helps Oracle Siebel customers understand the real position Siebel technology holds in the market, why the conventional wisdom about the product is often wrong, and what the trends driving the misconceptions in the market. The report also</span> <span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;">offers pragmatic advice for taking different Siebel implementations in different directions and how they will impact different careers. The report will be available on the Constellation website </span><span class="aBn" data-term="goog_387792487" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">Wednesday, September 18, 2013</span></span> at:</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="color: #333333; font-family: Arial, sans-serif; font-size: 10pt; line-height: 13px;"></span></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792488" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">9:30 a.m.</span></span> US Pacific time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792489" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">10:30 a.m.</span></span> US Mountain time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792490" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">11:30 a.m.</span></span> US Central time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792491" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">12:30 a.m.</span></span> US Eastern time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792492" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">17:30</span></span> UK time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span class="aBn" data-term="goog_387792493" style="border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; position: relative; top: -2px; z-index: 0;" tabindex="0"><span class="aQJ" style="position: relative; top: 2px; z-index: -1;">18:30</span></span> Central European time</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br />Webinar Information: To register for this complimentary webinar, go to: <a href="https://www3.gotomeeting.com/register/578393734" style="color: #1155cc;" target="_blank">https://www3.gotomeeting.com/<wbr></wbr>register/578393734</a></div>
Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-73651194260333041982013-09-05T18:34:00.000+10:002013-09-05T19:12:06.741+10:00Open UI: Tab Order DefectIn a scene from The Matrix I, Neo has a moment of deja vu, when he sees a black cat walk by twice. His companions freeze in their tracks, because this usually means The Matrix has been altered. Readers of Impossible Siebel, also had their black cat moment, when they discovered the <a href="http://www.impossiblesiebel.com/2009/12/siebel-8-tab-order-defect-on-popup.html">Tab Order defect in 8.1.1.1</a>, and then saw the same <a href="http://www.impossiblesiebel.com/2010/08/set-tab-layout-order-defect-8112.html">Tab Order defect again in 8.1.1.2</a>. Just like that deja-vu moment, here we are again facing a Tab order defect in Open UI popup applets.<br />
<br />
This problem affects any popup applet in OUI that has a custom tab sequence. To see this problem visually, goto any applet, enter query mode, and click on the Query Assistant applet.
<br />
<br />
Right click on the first control this applet, and inspect the source for this element.
<br /><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGiNVEYrJo6K5C2-pssZ_LC1DV_wIOfWbkrJREpec3fBZR1SnbFZkRIpCKkJcR3GHq_nVGYaGf4wSaOvC9TqR5kX3PQRKkMu5aVSH0JxQz9DKCt6rCBRwI1W4I5XpsNWev7qKuoHIj25A7/s1600/2_QA_Applet_fld1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGiNVEYrJo6K5C2-pssZ_LC1DV_wIOfWbkrJREpec3fBZR1SnbFZkRIpCKkJcR3GHq_nVGYaGf4wSaOvC9TqR5kX3PQRKkMu5aVSH0JxQz9DKCt6rCBRwI1W4I5XpsNWev7qKuoHIj25A7/s400/2_QA_Applet_fld1.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Do the same for other controls and buttons on this applet.
By default, all controls on a popup applet have a tab index of 0.
<br /><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDNc_0hifMxCTbdrfpoh0pF-WPQT9wUSPVm1lyzER9dqbd4F3oUVeA6D7Fz2e5hwm0i78i9RkzrhGTofuk-DpgTFL6qvU3Vnxy2rj-ALMDNP5nLRsoev_0_WpkUWPPmCe0C_pp1lmUQImk/s1600/3_QA_Applet_LastControl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDNc_0hifMxCTbdrfpoh0pF-WPQT9wUSPVm1lyzER9dqbd4F3oUVeA6D7Fz2e5hwm0i78i9RkzrhGTofuk-DpgTFL6qvU3Vnxy2rj-ALMDNP5nLRsoev_0_WpkUWPPmCe0C_pp1lmUQImk/s400/3_QA_Applet_LastControl.png" width="400" /></a><br /><br />
Next, find this applet in Tools, and add a custom Tab sequence, the actual sequence doesn't matter, as long as it is defined. This causes Siebel to produce the tabIndex attribute, and provide an actual sequence.
<br />
<br />
After our little modification, inspect the source code again, and it should look something like this.
<br />
<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3FKrY736co-4odE5suQs0WKoVb5Doq0XKmR7tyH5OiRHyhSo9vMmERwZWHkgA98J91RJa3bpQHU8gj7f-Cxa64PjW-Y6fCgJvF6IXWeQpkarqgEXguiyEOFADsGKvz1-YRTgSFaotjgTV/s1600/OUI_Tab_Index5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3FKrY736co-4odE5suQs0WKoVb5Doq0XKmR7tyH5OiRHyhSo9vMmERwZWHkgA98J91RJa3bpQHU8gj7f-Cxa64PjW-Y6fCgJvF6IXWeQpkarqgEXguiyEOFADsGKvz1-YRTgSFaotjgTV/s400/OUI_Tab_Index5.png" width="400" /></a><br />
<br />
<insert pic="">
This looks good, Siebel correctly generates the correct tab sequence, however try tabbing through all the controls on the applet, and watch what happens when the the last tab sequence is reached
<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghI2nxXbORnNsrYRWWLzjl0smMlubMjUzm-dk7KNPj1uDvutx2Kwz3Qfb5RHfW1qRznm_L95dvRMyl1-bKY_XBpBx2mpyhaNgcwpAb7-1bYpks9Eof3ngTUSP_EUGheS4kBoCpPLfwNZkD/s1600/4_QA_Applet_Err.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghI2nxXbORnNsrYRWWLzjl0smMlubMjUzm-dk7KNPj1uDvutx2Kwz3Qfb5RHfW1qRznm_L95dvRMyl1-bKY_XBpBx2mpyhaNgcwpAb7-1bYpks9Eof3ngTUSP_EUGheS4kBoCpPLfwNZkD/s400/4_QA_Applet_Err.png" width="400" /></a><br /><br />
The tab order doesn't cycle back to the first control as it did before, but it jumps back to the base applet behind the popup applet. This causes a commit, and can produce the above error, depending on what your base applet is.
<br /><br />
The reason behind this is, Siebel provides each of the base applets with a starting range for the tab sequence. The first applet starts at 1000, the next starts at 2000, and so on. When a popup is invoked, the controls on that applet are 0, if no tab sequence is specified, when a tab sequence is applied Siebel produces a tab sequence starting from 10000. When the last control is reached on the popup applet, it naturally returns back to the first applet, causing a commit and consequently an error.
<br /><br />
<b>Solution</b>
<br /><br />
1. Create a global render <br />
2. Detect if the applet is a popup<br />
3. Check for a custom tabIndex sequence<br />
4. Put a custom event handler on the last tab index<br />
5. Move the cursor back to the first control, when it reaches the last control
<br /><br />
<b>Steps</b>
<br /><br />
The strategy to create a global handler has already been discussed in the <a href="http://www.impossiblesiebel.com/2013/07/open-ui-mouseover-tool-tips-part-1.html">Open UI: Mouseover Tool Tips - Part 1</a> article.
<br /><br />1. In summary create the following JS file
<br /></insert><br />
<pre class="brush:js">//GlobalShowUI.js
if(typeof( SiebelAppFacade.PhysicalRenderer.prototype.bShowUIProxy ) === "undefined"){
SiebelAppFacade.PhysicalRenderer.prototype.bShowUIProxy=true;
SiebelAppFacade.PhysicalRenderer.prototype.ShowUI=(function(){
var PRShowUI = SiebelAppFacade.PhysicalRenderer.prototype.ShowUI;
return function(){
Global_PreShowUI.apply(this, arguments);
PRShowUI.apply(this, arguments);
Global_PostShowUI.apply(this, arguments);
};
}());
}
//put Global Pre ShowUI logic here
function Global_PreShowUI(){
var pm=this.GetPM();
if($("div[name='popup']").length>0){
SiebelApp.ABC.fixPopupFormAppletTabOrder(pm);
}
}
//put Global Post ShowUI logic here
function Global_PostShowUI(){
}</pre>
<br />
2. Add an entry into the custom_manifest.xml<br />
<br />
3. Add the following code sample into your client side script library.<br />
<br />
<pre class="’brush:js’">
SiebelApp.ABC.fixPopupFormAppletTabOrder=function (pm){
/*************************************
SAMPLE ONLY, NOT FOR PRODUCTION USE!
*************************************/
var oAppletTabIndex,aAppletTabIndex;
//Get all popup applet controls with tabindex
oAppletTabIndex = $("div[name='popup']").find("div.mceGridField>input[tabindex], button[tabindex]");
if(oAppletTabIndex.length>0){
//turn jquery object into array for sorting
aAppletTabIndex = jQuery.map (oAppletTabIndex, function( o) {
return ($(o).attr("tabindex")>0)?{ tag: $(o).prop("tagName"), seq: $(o).attr("tabindex"), sel: ($(o).prop("tagName")=="BUTTON")?"[id='"+$(o).attr("id")+"_Ctrl']":"[name='"+$(o).attr("name")+"']" }:null;
});
//sort on seq
aAppletTabIndex.sort(function(o1, o2) { return o1.seq > o2.seq ? 1 : o1.seq < o2.seq ? -1 : 0; });
if(aAppletTabIndex.length>0){
var sSelectorFirst=aAppletTabIndex[0].sel;
var sSelectorLast=aAppletTabIndex[aAppletTabIndex.length-1].sel;
//attach jquery handler on last tab index, and set focus back to the first tab index
$(sSelectorLast).blur(function() {
$(sSelectorFirst).focus();
});
$(sSelectorFirst).focus();
}
}
/*************************************
SAMPLE ONLY, NOT FOR PRODUCTION USE!
*************************************/
}
</pre>
<br />
<br />
<b>Code Explanation</b>
<br />
<br />
<pre class="’brush:js’">
//Get all popup applet controls with tabindex
oAppletTabIndex = $("div[name='popup']").find("div.mceGridField>input[tabindex], button[tabindex]");
}
</pre>
Grabs all fields and buttons on the popup applet where there is a tab index defined.
<br />
<br />
<pre class="’brush:js’">
//turn jquery object into array for sorting
aAppletTabIndex = jQuery.map (oAppletTabIndex, function( o) {
return ($(o).attr("tabindex")>0)?{ tag: $(o).prop("tagName"), seq: $(o).attr("tabindex"), sel: ($(o).prop("tagName")=="BUTTON")?"[id='"+$(o).attr("id")+"_Ctrl']":"[name='"+$(o).attr("name")+"']" }:null;
});
}
</pre>
The above command uses jQuery.map, to turn the first jquery object into a filtered array, of objects that contains the control selector, and tab sequence.
<br />
<br />
<pre class="’brush:js’">
//sort on seq
aAppletTabIndex.sort(function(o1, o2) { return o1.seq > o2.seq ? 1 : o1.seq < o2.seq ? -1 : 0; });
</pre>
Apply a sort on the new array, based on the sequence property that we created using the jQuery.map command.
<br />
<br />
<pre class="’brush:js’">
var sSelectorFirst=aAppletTabIndex[0].sel;
var sSelectorLast=aAppletTabIndex[aAppletTabIndex.length-1].sel;
//attach jquery handler on last tab index, and set focus back to the first tab index
$(sSelectorLast).blur(function() {
$(sSelectorFirst).focus();
});
</pre>
Once we have a sorted array, we can use the selector attribute to attach a handler to the last tab index control, which forces focus back to the first control
<br /><br />4. Restart your client, and now enjoy your new found love for tabIndex
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-76109788594695296362013-08-27T20:15:00.000+10:002014-11-08T15:07:46.159+11:00Rapid Browser Script DevelopmentThis article was written pre Open UI and was locked up in vault, because Browser Script was becomming old school. But as an early user of Open UI, I've found the need to rapidly modify and troubleshoot browser script issues, and remembered the same technique which is used in HI, is also applicable to Open UI.
<br />
<br />
This article might be more appropriate for a Browser Script reunion party, but it has been released for those who may still struggle with Browser Script, and for Open UI customers who may still rely on legacy Browser Script.
<br />
<br />
-----------------------------------------------------------------------------------
<br />
<br />
I asked a trusty colleague to put a line of browser script behind a certain applet and perform an incremental compile on the server for me.
<br />
<br />
<b>Colleague:</b> What browser script command do I need to put on this applet? <br />
<b>Me:</b> Anything you want, make it display an alert for me.<br />
<b>Colleague:</b> Where should I put it? Applet Load? PreInvoke? <br />
<b>Me:</b> It doesn't matter, just make sure it compiles.
<br />
<br />
10 minutes later, the server was rebooted, I got my new browser scripted applet and my colleague was free to continue his own work.
<br />
<br />
Unfortunately, when I took a look at the browser script behind the applet, my colleague inadvertently put a typo in the code, which caused the following error in the <a href="http://www.impossiblesiebel.com/2011/06/browser-script-debugger.html">IEDTB console</a>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3scYr0HQccumeTdbTYDM_UYAsXezSeTZKz37maSsezSQGVwpiLFKZvhQIU0q53TF1AqpOTB0mNub_poUpu53RHHFuwMJGk2md6NPyAFly1YQSyINV-Rw8CVXX4haazDoChNvpIz5Wr58d/s1600/RpdBScr_broken_scr_err.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3scYr0HQccumeTdbTYDM_UYAsXezSeTZKz37maSsezSQGVwpiLFKZvhQIU0q53TF1AqpOTB0mNub_poUpu53RHHFuwMJGk2md6NPyAFly1YQSyINV-Rw8CVXX4haazDoChNvpIz5Wr58d/s400/RpdBScr_broken_scr_err.png" /></a>
<br />
<br />
Fortunately this doesn't matter for what we're about to do. In fact, the browser script didn't have to be valid, it can be total junk, but as long as it compiles and produces the browser script files, we're in business. What this does is forces Siebel to produce the necessary "hooks" from the UI to the external JS files.
<br />
<br />
First we're going to fix that typo. Goto the web server, and find the generated browser script JS file for that Applet.
<br />
<br />
You'll find that it will look something like this.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeW0W7TiPqAC3yn_hjVymf8KNXdcWTFqQMFi-zP3PVAHnh7u1BnV2CHAtf9C914JL2fTz2kJcoUI_mpFina-f2da2xnwFzZht2oYOCugZBijqfuBxpBjwXL9K42Oh5gZFyZciSRKnX3WGI/s1600/RpdBScr_broken_scr.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeW0W7TiPqAC3yn_hjVymf8KNXdcWTFqQMFi-zP3PVAHnh7u1BnV2CHAtf9C914JL2fTz2kJcoUI_mpFina-f2da2xnwFzZht2oYOCugZBijqfuBxpBjwXL9K42Oh5gZFyZciSRKnX3WGI/s400/RpdBScr_broken_scr.png" /></a>
<br />
<br />
We can fix that typo by re-writing the browser script error on the fly and instead of displaying a dialog box on Applet PreInvoke, we will re-implement the code to use a less obtrusive console.log on <i>Applet Load</i>, which means we will have to introduce a new OnLoad handler.
<br />
<br />
Change your JS file to the following.
<br />
<br />
<pre class="’brush:js’">function Web_Browser_Entry_Applet_PreInvokeMethod(name, inputPropSet){
return ("ContinueOperation");
}
//Artificial Onload method hanlder
function Web_Browser_Entry_Applet_Load(applet){
//write to the IEDTB console
console.info("I Love Disco");
}
function Web_Browser_Entry_Applet(applet){
if(applet != null){
this._applet = applet;
applet.shado = this;
}
}
new Web_Browser_Entry_Applet(null);
Web_Browser_Entry_Applet.prototype=new top.JSSAppletShadow();
Web_Browser_Entry_Applet.prototype.OnPreInvoke=Web_Browser_Entry_Applet_PreInvokeMethod;
//Attach a new handler for Onload
Web_Browser_Entry_Applet.prototype.OnLoad=Web_Browser_Entry_Applet_Load;
theApplication=top.theApplication;
TheApplication=top.theApplication;
</pre>
<br />
<br />
Open the IE Developer Toolbar by pressing F12, clear your browser cache, disable script debugging, and reload the Screen. Follow those steps exactly and your new change will take effect immediately.
<br />
<br />
Your screen should look like this.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmLB__L6btnAEXmkH1V0v-vlYmUUwt1AsQg85GW5VHP7g-bd1GTeNMDfw9MTotJN7u0xW-p0ghp3xa_Obmp3KQYsH4rA7JGl_7dI6o0te1puQC-ctZyBtQAhFsqYLvshoiZ4XGXeDWKZWZ/s1600/RpdBScr_ilovedisco_console.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmLB__L6btnAEXmkH1V0v-vlYmUUwt1AsQg85GW5VHP7g-bd1GTeNMDfw9MTotJN7u0xW-p0ghp3xa_Obmp3KQYsH4rA7JGl_7dI6o0te1puQC-ctZyBtQAhFsqYLvshoiZ4XGXeDWKZWZ/s400/RpdBScr_ilovedisco_console.png" /></a>
<br />
<br />
Next let’s give ourselves direct access to the Applet scope from the Browser, this will allow us to write Browser script on the fly in context of the Applet, without reloading the browser!
<br />
<br />
Change your browser script file to include the following
<br />
<br />
<pre class="’brush:js’">//recreate the function on the global scope
top.OnPreInvoke=function(name, inputPropSet){
console.info(name);
return ("ContinueOperation");
}
//recreate the function on the global scope
top.OnLoad=function(applet){
//create a global reference to the current applet
top.thisApplet=this;
console.info("I Love Disco");
}
function Web_Browser_Entry_Applet(applet){
if(applet != null){
this._applet = applet;
applet.shado = this;
}
}
new Web_Browser_Entry_Applet(null);
Web_Browser_Entry_Applet.prototype=new top.JSSAppletShadow();
//repoint the prototype functions to our new globals
Web_Browser_Entry_Applet.prototype.OnPreInvoke=top.OnPreInvoke;
Web_Browser_Entry_Applet.prototype.OnLoad=top.OnLoad;
theApplication=top.theApplication;
TheApplication=top.theApplication;
</pre>
<br />
<br />
There are two key pieces in play here.
<br />
<br />
1) top.OnPreInvoke;
<br />
<br />
This line shifts execution to a global function that we’ve attached to the main window. Browser Script files are loaded from a hidden frame, so it must be attached to the <i>top</i>, for the console to access.
<br />
<br />
This global reference allows us to modify the definition of the function, and run new code without reloading the browser.
<br />
<br />
2) top.thisAppet
<br />
<br />
This is similar to the above, but this line provides us with access to the Applet instance.
<br />
<br />
Click Query, and Cancel, to see the results of this dynamic browser script.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAW4nFc90-e1yKgqqT2kho63xNlWgw4mb2yZs3m-ud31w7J11DDWRYcZKijlJxFqeI3mEYH3ex08jO8sL2enrnEQL3MdcPTi99dkUks16Q0lspOolyMmedIODYhhy3BcBo4lov0gLMj51W/s1600/RpdBScr_test_thisApplet_PreInv_mirror.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAW4nFc90-e1yKgqqT2kho63xNlWgw4mb2yZs3m-ud31w7J11DDWRYcZKijlJxFqeI3mEYH3ex08jO8sL2enrnEQL3MdcPTi99dkUks16Q0lspOolyMmedIODYhhy3BcBo4lov0gLMj51W/s400/RpdBScr_test_thisApplet_PreInv_mirror.png" /></a>
<br />
<br />
<br />
<br />
We now have direct access to the runtime context of the Applet, and we can develop directly from the IE console.
<br />
<br />
Overwrite the PreInvoke Handler, by pasting the following code into the console. Click “Query”, and we now see a dialog box.
<br />
<br />
<pre class="’brush:js’">top.OnPreInvoke=function(name, inputPropSet){
console.info(name);
switch(name){
case "NewQuery":
alert(name);
break;
}
}
</pre>
<br />
<br />
Type the following code into the console, and what happens to the Description field
<br />
<br />
<pre class="’brush:js’">top.thisApplet.FindControl("Description").SetValue("I Love Disco");
</pre>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtD98v3_lIA-V-x5XGM3wfC-a7iQvb3tY4b_FKgFlhLpyw4Kq84cLtfW0kORLGVmgNbXXkb9AciCA3eWfzedODqzVCFVP2X2zq5ISln1SLRkgWwSBEy8VYP9UCOf95OCHwSYtU2xMjzuSG/s1600/RpdBScr_test_thisApplet_SetControl.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtD98v3_lIA-V-x5XGM3wfC-a7iQvb3tY4b_FKgFlhLpyw4Kq84cLtfW0kORLGVmgNbXXkb9AciCA3eWfzedODqzVCFVP2X2zq5ISln1SLRkgWwSBEy8VYP9UCOf95OCHwSYtU2xMjzuSG/s400/RpdBScr_test_thisApplet_SetControl.png" /></a>
<br />
<br />
We have just learned how to rewrite Browser Script on the fly, and handle events that are not defined in the repository.
<br />
<br />
The last step in this Rapid Browser Script development process, is to make sure that when you are happy with your browser script, remove those global references, copy the logic back into Tools, in the correct event handler and compile it to validate your handy work.
<br />
<br />
-----------------------------------------------------------------------------------
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com2tag:blogger.com,1999:blog-6992129293870658291.post-30467393082376244022013-08-26T23:21:00.002+10:002013-08-26T23:27:29.786+10:00Open UI: Property Set Methods (GetChildByType)<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-new-structure.html">Open UI: New Property Set Structure</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-copy.html">Open UI: Property Set Methods (Copy, DeepCopy, Clone)</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-fixing-copy.html">Open UI: Property Set Methods (Fixing Copy) </a><br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-why-clone_20.html">Open UI: Property Set Methods (Why Clone?)</a>
<br />
<br />
The <a appendix_a_api20.html="" books="" cd="" config_open_ui="" docs.oracle.com="" href="http://www.blogger.com/%E2%80%9D" http:="">new chapter in bookshelf</a> on Open UI Property Sets has a new method called <i>GetChildByType</i>. This has to be the most interesting method that we’ve seen so far. I’ve seen numerous custom implementations of this handy method written in eScript, and it’s about time Siebel have provided it out of the box, but sadly its only available on the Browser.
<br />
<br />
To understand how this can be useful, the follow is an example of code that was written to loop through a SiebelMessage n times to look for a child Property Set with a certain type.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2uaYvst3-RLhgjfFk3D0YCtfdmcJ58v7dv5_R455-qm6nmOE9x7Cl-vzweUQ-P_dXCcIaRNFXMsMdqPNclogMdwGLJNyAP0MV0I_CdIH7223dmUWnIscQdhOdYmL33wZUvE58N1KN_3ol/s1600/OUI_PS_Methods_FindChildByType_bad_eg.png" imageanchor="1"><img border="0" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2uaYvst3-RLhgjfFk3D0YCtfdmcJ58v7dv5_R455-qm6nmOE9x7Cl-vzweUQ-P_dXCcIaRNFXMsMdqPNclogMdwGLJNyAP0MV0I_CdIH7223dmUWnIscQdhOdYmL33wZUvE58N1KN_3ol/s400/OUI_PS_Methods_FindChildByType_bad_eg.png" width="400" /></a>
<br />
<br />
You need to have eyeballs of steel to follow this example, but this should be a thing of the past. With this new method, we <i>should</i> be able to reduce the above example to 1 line.<br />
<br />
Lets test it out.
<br />
<br />
<pre class="”brush:js”">
//setup test case
//construct a deep hierarchy
var ps=theApplication().NewPropertySet();
var psChild1=theApplication().NewPropertySet();
var psGrandChild1=theApplication().NewPropertySet();
var psGrandChild2=theApplication().NewPropertySet();
var psGrandChild3=theApplication().NewPropertySet();
var psGreatGrandChild1=theApplication().NewPropertySet();
var psChild2=theApplication().NewPropertySet();
ps.SetType("Parent");
ps.SetValue("ParentValue");
ps.SetProperty("Mum","Georgette");
ps.SetProperty("Dad","George");
//first level child
psChild1.SetType("Child 1");
psChild1.SetProperty("Name","Bob");
psChild1.SetProperty("Gender","Male");
psGrandChild1.SetType("Grand Child 1");
psGrandChild1.SetProperty("Name","Bobby's Kid 1");
psGrandChild1.SetProperty("Gender","Male");
psGreatGrandChild1.SetType("Great Grand Child 1");
psGreatGrandChild1.SetProperty("Name","Bobby's Grand Kid 1");
psGreatGrandChild1.SetProperty("Gender","Male");
psGrandChild2.SetType("Grand Child 2");
psGrandChild2.SetProperty("Name","Bobby's Kid 2");
psGrandChild2.SetProperty("Gender","Male");
//first level child
psChild2.SetType("Child 2");
psChild2.SetProperty("Name","Jane");
psChild2.SetProperty("Gender","Female");
psGrandChild3.SetType("Grand Child 3");
psGrandChild3.SetProperty("Name","Janes's Kid 2");
psGrandChild3.SetProperty("Gender","Male");
psGrandChild1.AddChild(psGreatGrandChild1);
psChild1.AddChild(psGrandChild1);
psChild1.AddChild(psGrandChild2);
psChild2.AddChild(psGrandChild3);
ps.AddChild(psChild1);
ps.AddChild(psChild2);
console.log("Test case 1: " + ps.GetChildByType("Child 1").GetType() );
console.log("Test case 2: " + ps.GetChildByType("Child 2").GetType() );
console.log("Test case 3: " + ps.GetChildByType("Grand Child 1") );
console.log("Test case 4: " + ps.GetChildByType("Grand Child 2") );
</pre>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhorWdUAUoSDVHRVb2CdXu_XQL8yKufXtF5YU2Zi6tJEquIM78_aXo60axeGGkcUJQX7JeedsY8sLjHsmAvUhUDLcijn6iXdkwAQQY1TiuBMQuxw0Vca-OHAdpKm9uvFUYwe1ihsOQwXso1/s1600/OUI_PS_Methods_GetChildByType_Result.png" imageanchor="1"><img border="0" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhorWdUAUoSDVHRVb2CdXu_XQL8yKufXtF5YU2Zi6tJEquIM78_aXo60axeGGkcUJQX7JeedsY8sLjHsmAvUhUDLcijn6iXdkwAQQY1TiuBMQuxw0Vca-OHAdpKm9uvFUYwe1ihsOQwXso1/s400/OUI_PS_Methods_GetChildByType_Result.png" width="400" /></a>
<br />
<br />
Disapointingly, the results above show that “GetChildByType” only returns child Property Sets directly attached to the input Property Set, in other words, it doesn’t perform a recursive search of the entire Property Set as we might hope.
<br />
<br />
<b>Custom GetChildByType</b>
<br />
<br />
This falls back onto the customer to implement a custom <i>GetChildByType</i> that actually searches beyond the first level.<br />
<br />
The safest place to house this new Method, is in a custom client side library.
<br />
<br />
There are multiple approaches on how to build this client side library, but for this article, we will stick with a simple example using the same style of registering a custom PR/PM.<br />
<br />
<insert manifest="" picture="">
<br /><br />
For educational purposes, the following code shows how this function can be built, please don’t use the code without understanding what it does.
<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYf483_z8dSpkxc_JHUP-_zPztMthu8Qjq2RYuAi4tOFuKUJEgpR4PPn0SOmHsaYWMKAVPFINRJpu_LSKN0E_fHN8za50riX0V1OKBi3uoXd0Dp8cYj0p8iamj-AmVRnW56O5IWoVKpiQK/s1600/OUI_PS_Methods_FindChildByType_util_fn.png" imageanchor="1"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYf483_z8dSpkxc_JHUP-_zPztMthu8Qjq2RYuAi4tOFuKUJEgpR4PPn0SOmHsaYWMKAVPFINRJpu_LSKN0E_fHN8za50riX0V1OKBi3uoXd0Dp8cYj0p8iamj-AmVRnW56O5IWoVKpiQK/s400/OUI_PS_Methods_FindChildByType_util_fn.png" width="400" /></a>
<br /><br />
Next ensure that you load your custom logic in the custom_manifest.xml
<br /><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39vXq5jZh2B0cOHg35QDrEB4fDI-goIBXVEo6qH2BeA8eZDW9XNVBnngitqBc_ZoEzCXAdNFpkEiSuUi8QpYRYvZbWPkdmFRc8IS3Mw6Q2K2uf5OwF2DILoZroIs845ieZwY3W50h5ZPJ/s1600/OUI_PS_Methods_FindChildByType_custom_manifest.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39vXq5jZh2B0cOHg35QDrEB4fDI-goIBXVEo6qH2BeA8eZDW9XNVBnngitqBc_ZoEzCXAdNFpkEiSuUi8QpYRYvZbWPkdmFRc8IS3Mw6Q2K2uf5OwF2DILoZroIs845ieZwY3W50h5ZPJ/s400/OUI_PS_Methods_FindChildByType_custom_manifest.png" /></a>
<br /><br />
Heres how one would use this new library function.
<br />
<pre class="brush:js">
var psGrandChild=SiebelApp.ABC.GetChildByType(ps,"Grand Child 2");
//returns Property Set
</pre>
<br />
<br />
<b>Conclusion</b><br />
<br />
<i>GetChildByType</i> is just one of the many new methods exposed in the Open UI Property Set. Although the intentions were well made, the limitations of the current implementation, make it hard for customers to embrace. Until Siebel provides a method in future to perform a recursive search, customers will do well to augment Siebel's API, with their own client side libraries.
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-59009341505004364222013-08-20T22:02:00.000+10:002013-08-20T22:02:34.600+10:00Open UI: Property Set Methods (Why Clone?)
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-new-structure.html">Open UI: New Property Set Structure</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-copy.html">Open UI: Property Set Methods (Copy, DeepCopy, Clone)</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-fixing-copy.html">Open UI: Property Set Methods (Fixing Copy) </a><br />
<br />
<br />
Previously on <a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-copy.html">Open UI: Property Set - Methods (Copy, DeepCopy, Clone)</a>, we discovered two new ways to copy a Property Set (DeepCopy and Clone).
<br />
<br />
DeepCopy is similar to Copy, except it merges two Property Sets together, while Clone performs a full copy of a PropertySet just like Copy, which raises the question around the meaning of life for Clone...until now.
<br />
<br />
To understand why Clone exists, we need to go back to the basics of ECMA script, which eScript, Browser Script and Java Script are all based upon.
<br /><br />
<b>Argument Passing</b>
<br /><br />It is common knowledge, that there are two kinds of variables.
<br /><br />
<blockquote>
Primitive: <br />
<i>Number, Boolean, String, Undefined, Null</i>
<br /><br />
Complex/Composite: <br />
<i>Object, Array, Property Set, BusComp, Business Service, BusObject</i>
</blockquote>
<br /><br />
Property Sets, BusComps, BusObject, Business Services are specific to the Siebel environment, and are considered to be complex/composite Objects, because they are derived from the base Object.<br />
<br />
<br />
It is also "common" knowledge that complex/composite objects are passed into functions by reference. This view is supported by Bookshelf.
<br /><br />
<a href="http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSLOverview35.html#wp1004085">Passing Variables to Functions in Siebel eScript</a>
<br /><br />
<i>Composite types such as objects and arrays are passed by reference.</i>
<br /><br />
However this is a common misconception, in fact all function arguments are actually passed in by value. Siebel professionals who work with Siebel Inputs/Outputs day in and day out, will testify to the opposite.
<br /><br />
This is not the first time we've challenged the view of the world, so let me back this up with evidence, and what better way than to do it than with Siebel's Property Set <b>Copy</b> and <b>Clone</b>?<br />
<br /><br />
<pre class="brush:js">
//Create new Property Set
var ps = SiebelApp.S_App.NewPropertySet();
//Set Type on original PS
ps.SetType("A");
console.log( ps.GetType() );
//Type stores "A"
//Perform Copy on ps
copyPS(ps);
function copyPS(ps){
var ps2 = SiebelApp.S_App.NewPropertySet();
//Create a new PS and set the type
ps2.SetType("B");
//perform a copy on ps2
ps.Copy(ps2);
}
console.log( ps.GetType() );
//Type now stores "B"
</pre>
<br /><br />
The above test case starts off with a Property Set with a Type "A", which is passed into copyPS, which modifies the original Property Set's Type to "B". This is what we know and expect.
<br /><br />
Watch what happens when we use <i>Clone</i>.
<br /><br />
<pre class="brush:js">
//Create new Property Set
var ps = SiebelApp.S_App.NewPropertySet();
//Set type on Original PS
ps.SetType("A");
console.log( ps.GetType() );
//Type stores "A"
//Perform Clone on ps
clonePS(ps);
function clonePS(ps){
var ps2 = SiebelApp.S_App.NewPropertySet();
//Create a new PS and Set the type to a different value
ps2.SetType("B");
//If this argument was passed in by Reference
//it should contain the new type above.
ps=ps2.Clone();
}
console.log( ps.GetType() );
//Type still stores "A",
//the cloned value was lost!
</pre>
<br /><br />
With the same expectation as above, if <i>ps</i> were passed in as a reference, we would see that the original Property Set's type would be modified to "B", instead the original Property Set remains’ unchanged.
<br /><br />
Here is another derivative of the above example
<br /><br />
<pre class="brush:js">
var ps = theApplication().NewPropertySet();
ps.SetType("A");
var ps2 = theApplication().NewPropertySet();
ps2.SetType("B");
//Perform Clone on ps
clonePS(ps, ps2);
function clonePS(ps, ps2){
//If this argument was passed in by Reference
//it should contain the new type above.
ps=ps2.Clone();
}
console.log( ps.GetType() );
//Type still stores "A",
//the cloned value was lost!
</pre>
<br />
<br />
In the second example, I’ve moved both <i>ps</i> and <i>ps2</i> declarations to global scope, and passed in the both Property Set "references". The function <i>clonePS</i> tries to reassign the reference but fails.
<br />
<br />
<br />
<br />
To explain this behaviour, think of <i>ps</i> as a reference that is being passed in by value and not as a reference passed in by reference. The reference can be used to modify the original Object, but the reference to the original object itself cannot be altered inside the function. The local copy can be changed to point to another object, however this local copy is independent from our original object.
<br /><br />
eScript developers will be wondering, will this really apply to them? Lets fire up <a href="http://www.impossiblesiebel.com/2013/07/the-harness.html">The Harness</a>, and create a new test case using Server Script.
<br /><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvObw2D-G-WrbLzL78XQ9SvUiNt-LCgtCxHetfOb-u5WsbT-7waKVSFS6gAyOtLOkmXwaeuZ31jz-Wm9IDc0rbteD-200PDadtZB6Xgr7Yqy1BGEKV0Z6fx_hrKKW6XtKz2IbEWMO9J498/s1600/OUI_PS_Methods_WhyClone_eScript_test.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvObw2D-G-WrbLzL78XQ9SvUiNt-LCgtCxHetfOb-u5WsbT-7waKVSFS6gAyOtLOkmXwaeuZ31jz-Wm9IDc0rbteD-200PDadtZB6Xgr7Yqy1BGEKV0Z6fx_hrKKW6XtKz2IbEWMO9J498/s400/OUI_PS_Methods_WhyClone_eScript_test.png" /></a>
<br /><br />
The above test case shows <i>ps1</i> and <i>ps2</i> being passed into a function, where the <i>ps1</i> reference is set, and then reassigned to another Property Set. From our understanding above, the following statement fails
<br /><br />
<i>ps1=ps2</i>
<br /><br />
There are no surprises at this point, as the results reflect what we saw in the browser.
<br /><br />
<br /><br />
We can conclude that this behaviour exists in eScript/BScript and JavaScript, which are all flavours of the ECMA specification. The only exception to this rule is that with eScript, we get a special function argument modifier "&" that allows us to pass a reference by reference.
<br /><br />
<b>Conclusion</b>
<br />
<br />
Siebel designed Clone to behave fundamentally different from Copy and DeepCopy, and provides it as a distinct alternative for those circumstances that the original Property Set should be preserved.
<br />
<br />
On the surface Copy, DeepCopy, and Clone look like they behave the same, but its only when we look beneath the surface, that we appreciate the subtleties of Siebel Property Sets. It brings me back to my favourite Yum cha restaurant, and being presented with Prawn & Basil dumpling, Deep fried Prawn Dumpling, and Prawn Gyoza Dumpling.
<br />
<br />
All claim to be Prawn dumplings, they have different presentations, but it’s not until you dig into it, that you begin to enjoy the subtleties of Prawn that is deep friend, pan fried, and steamed. The next time you copy that Property Set, spare a thought for the Siebel engineers who provided the different flavours of Copy, DeepCopy, and Clone, for you to enjoy.
<br />
<br /> Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0tag:blogger.com,1999:blog-6992129293870658291.post-34706667879118291232013-08-07T21:40:00.000+10:002013-08-28T16:18:52.446+10:00Open UI: Mouse over Tooltips - Part 2<a href="http://www.impossiblesiebel.com/2013/07/open-ui-mouseover-tool-tips-part-1.html">Open UI: Mouseover Tool Tips - Part 1</a>
<br />
<br />
This is a continuation of <a href="http://www.impossiblesiebel.com/2013/07/open-ui-mouseover-tool-tips-part-1.html">Open UI: Mouse Over Tooltips - Part 1</a>, where we invented our own <i>Pre_ShowUI</i>, and <i>Post_ShowUI</i> handlers. These handlers allow us to hook onto the physical renders base class <i>ShowUI</i> method, to trigger global behaviour each time a UI object is rendered.
<br />
<br />
Let’s imagine a solution where an administrator can log into the Siebel UI, identify an Applet, a Control or List column and specify some text. This will render a fancy mouse over tooltip over the control/list column, the next time the page is reloaded. No scripting, or configuration skills is required!.
<br />
<br />
<b>Sequence of events</b>
<br />
<br />
1. The user navigates to a view<br />
2. The page will load all the base applets in the view<br />
3. Post_ShowUI will fire for each applet that is rendered<br />
4. Read Values from Data source<br />
5. Attach tooltip to configured control
<br />
<br />
<b>Data source</b>
<br />
<br />
The data source can be as simple as a global JS configuration file, or in our case it will be retrieved from a table on the server. For the sake of simplicity our data source for this article will be the LOV table, with the following mappings.
<br />
<br />
Description = Applet Name<br />
LIC = Control Name<br />
Value = Tooltip message<br />
<br />
<br />
The LOV table is unsuitable for a number of obvious reasons, and it is used here only to illustrate the build for this Tool tip configuration. I’ve created some sample records, and filled some values, that we will use a bit later.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJjykg6RGHRPkbUlvhCB6XpWRDa87CXrZGOSJxOzAOccLSbDj2CFiRuXOjTF7W7xlGesGf-T14BAJwYaOwx-2rS_XsYyN2gNLBFQc2fQ80DZrmTfZe2N7acf18PHud3zvEsphkl3MNtxWX/s1600/OUI_TT2_LOVTooltipAdmin.png" imageanchor="1"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJjykg6RGHRPkbUlvhCB6XpWRDa87CXrZGOSJxOzAOccLSbDj2CFiRuXOjTF7W7xlGesGf-T14BAJwYaOwx-2rS_XsYyN2gNLBFQc2fQ80DZrmTfZe2N7acf18PHud3zvEsphkl3MNtxWX/s400/OUI_TT2_LOVTooltipAdmin.png" width="400" /></a>
<br />
<br />
<b>Tooltip Loader</b>
<br />
<br />
The Tooltip loader is fired from our custom global Post_ShowUI event, and performs the following functions.
<br />
<br />
1. Identify the current applet in context<br />
2. Query the data source for the tooltip definitions<br />
3. Attach tooltips to the Applet Controls/List columns
<br />
<br />
<b>Reading the Data source</b>
<br />
<br />
This job should be performed by a server side Business Service in tools, and for convenience I’ve used <a href="http://www.blogger.com/%E2%80%9Dhttp://www.impossiblesiebel.com/2013/07/the-harness.html%E2%80%9D">The Harness</a> to quickly build and unit test the POC for this article.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyj5tgIn5s_up5xAf2UEDwgCFLFzD4bbshYpxsUs3JqoNagsID2i-uO9NCKrzql0UpsXRpSVDMRC0snguuYO4MLX9nQoDBM1UCvfa8KI8cuncl612QGiRInGxK026wDUmWUw5l43lLy3ZV/s1600/OUI_TT2_TheHarness_LOV_Test2.png" imageanchor="1"><img border="0" height="343" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyj5tgIn5s_up5xAf2UEDwgCFLFzD4bbshYpxsUs3JqoNagsID2i-uO9NCKrzql0UpsXRpSVDMRC0snguuYO4MLX9nQoDBM1UCvfa8KI8cuncl612QGiRInGxK026wDUmWUw5l43lLy3ZV/s400/OUI_TT2_TheHarness_LOV_Test2.png" width="400" /></a>
<br />
<br />
The results pane shows the output structure that we want to send to the Browser, and confirms that our data is correctly populated in the Property Set.
<br />
<br />
There are a few custom commands in this example, which will be foreign to most Siebel customers.
<br />
<br />
<b>util.getLOVObjs</b> <br />
getLOVObjs is a eScript library function that queries the LOV table and returns an Array<br />
<b><br />[].ObjToStr</b> <br />
ObjToStr is a eScript library function that prints out any Object for debugging<br />
<b><br />[].PSToStr</b> <br />
Projects with the <a href="http://www.impossiblesiebel.com/2009/11/abs-framework-prototype-library.html">ABS framework</a> will recognise this utility. This prints out a Property Set for debugging<br />
<br />
<br />
Script libraries are described here in <a href="http://www.blogger.com/%E2%80%9Dhttp://docs.oracle.com/cd/B40099_02/books/UsingTools/UsingTools_ScriptEditors13.html%E2%80%9C">Bookshelf</a>. The implementation of the Script library is out of scope for this article, but the key take away from this example is, projects should be implementing utility libraries to encapsulate common functionality, and maximise reuse of script in the application.
<br />
<br />
<b>Tooltip loader logic</b>
<br />
<br />
The high level logic looks like this
<br />
<br />
1. Call retrieve Tooltips using a server side Business Service<br />
2. Get Controls map from the current applet<br />
3. Loop through Tooltip configuration <br />
4. Build Control/List Column jQuery Selector <br />
5. Attach Tooltip to Control/List Column <br />
<br />
<br />
<pre class="brush:js">SiebelApp.ABCToolTips.LoadAppletToolTips=function(pm){
try{
var sAppletId=pm().Get("GetFullId"),sApplet=pm().GetProxy().GetName(),sModId="JLETooltips";
//Remove all tooltip indicators
$("#"+sAppletId+" img["+sModId+"]").remove();
//look for table prefix, and also determine applet type
var oAppletProp=SiebelApp.ABCToolTips._GetAppletProp(sAppletId);
//Get Tooltip definition from server
var oTooltipCfg=SiebelApp.ABCToolTips._GetToolTipsFrSvr(sApplet);
if(oTooltipCfg.length>0){
// retrieve all controls on current applet
var oControlsMap=pm().Get("GetControls");
for(var sTooltipCntr in oTooltipCfg){
var oOpt=(oAppletProp.isListApplet)?SiebelApp.ABCToolTips.OptionsHeading:SiebelApp.ABCToolTips.Options;
oOpt.content.text = oTooltipCfg[sTooltipCntr]["Msg"];
//Lookup control definition
var oControl=oControlsMap[sTooltipCntr];
if(typeof oControl!=="undefined"){
var sIdSelector=SiebelApp.ABCToolTips._GetControlListColSelector(oAppletProp,oControl.GetName());
$(sIdSelector).qtip(oOpt);
$(sIdSelector).append("<img smodid="" src="images/icon_helptext.gif" true="" />");
}else{
}
}
}
}catch(e){
throw e;
}
}
SiebelApp.ABCToolTips._GetControlListColSelector=function(oAppletProp,sControlName){
var sControlNameUnd=sControlName.replace(/\s/g,"_");
var sIdSelector=( oAppletProp.isListApplet )?"#"+oAppletProp.sDataTablePrefix+"_"+sControlNameUnd:"#"+sControlNameUnd+"_Label";
return sIdSelector;
}
SiebelApp.ABCToolTips._GetAppletProp=function(sAppletId){
var oGridId=$("#"+sAppletId+" .ui-jqgrid-view");
var sDataTablePrefix="";
if(oGridId.length>0){
sGridId=oGridId.attr("id").replace("gview_","");
//column headers are prefixed with 'jqgh_' plus the table id
sDataTablePrefix="jqgh_"+sGridId;
var isListApplet=true;
}else{
var isListApplet=false;
}
return {"isListApplet":isListApplet,"sDataTablePrefix":sDataTablePrefix}
}
SiebelApp.ABCToolTips.Options={
content: {
prerender : true,
text: ""
},
}
SiebelApp.ABCToolTips.OptionsHeading=SiebelApp.ABCToolTips.Options;
</pre>
<br />
<br />
Explanation:
<br />
<pre class="brush:js">var sAppletId=pm().Get("GetFullId");
var sApplet=pm().GetProxy().GetName();
var sModId="JLETooltips";
//Remove all tooltip indicators
$("#"+sAppletId+" img["+sModId+"]").remove();
//look for table prefix, and also determine applet type
var oAppletProp=SiebelApp.ABCToolTips._GetAppletProp(sAppletId);
</pre>
<br />
<br />
The above lines performs some basic initialisation, and determines whether we are dealing with a Form or List Applet
<br />
<br />
<pre class="brush:js">var oTooltipCfg=SiebelApp.ABCToolTips._GetToolTipsFrSvr(sApplet);
</pre>
<br />
<br />
This method calls the server, and returns list of child Property Sets, as shown by the results pane of The Harness above.
<br />
<br />
The actual implementation of this Business Service isn’t provided in this article, because the LOV table isn’t the right Data source for a real solution, and the script library functions that I’ve used are unique to my local environment.
<br />
<br />
<pre class="brush:js">if(oTooltipCfg.length>0){
// retrieve all controls on current applet
var oControlsMap=pm().Get("GetControls");
// Loop around all the Tooltips retrieved from the server for the current applet
for(var sTooltipCntr in oTooltipCfg){
var oOpt=(oAppletProp.isListApplet)?SiebelApp.ABCToolTips.OptionsHeading:SiebelApp.ABCToolTips.Options;
oOpt.content.text = oTooltipCfg[sTooltipCntr]["Msg"];
//Lookup control definition
var oControl=oControlsMap[sTooltipCntr];
if(typeof oControl!=="undefined"){
var sIdSelector=SiebelApp.ABCToolTips._GetControlListColSelector(oAppletProp,oControl.GetName());
$(sIdSelector).qtip(oOpt);
$(sIdSelector).append("<img smodid="" src="images/icon_helptext.gif" true="" />");
}
}
}
</pre>
<br />
<br />
The block of code above is fairly well documented. However, attaching qTip itself requires a bit more explanation.
<br />
<br />
The syntax for attaching qTip Tooltips looks like this
<br />
<br />
$(sIdSelector).qtip(oOpt);
<br />
<br />
The form control selector is basically the Control name with spaces replaced with “_”, appended by “_Label”.
<br />
<br />
<pre class="brush:js">SiebelApp.ABCToolTips._GetAppletProp=function(sAppletId){
var oGridId=$("#"+sAppletId+" .ui-jqgrid-view");
var sDataTablePrefix="";
if(oGridId.length>0){
sGridId=oGridId.attr("id").replace("gview_","");
//column headers are prefixed with 'jqgh_' plus the table id
sDataTablePrefix="jqgh_"+sGridId;
var isListApplet=true;
}else{
var isListApplet=false;
}
return {"isListApplet":isListApplet,"sDataTablePrefix":sDataTablePrefix}
}
</pre>
<br />
<br />
List column selectors are a bit harder. It is a combination of a Grid prefix+ the Control name with spaces replaced with “_”. The function above shows the jQuery selector that I used to get the Grid Id.
<br />
<br />
Finally the <b>oOpt</b> object tells qTip what message to display, how to display the tooltip, and other options such as style.
<br />
<br />
oOpt.content.text = oTooltipCfg[sTooltipCntr]["Msg"];
<br />
<br />
In our example above, <b>oOpt.content.text</b> is the property that qTip will display as the message. More details can be found on the <a href="http://qtip2.com/">qTip website</a>
<br />
<br />
<b>Trigger</b>
<br />
<br />
The final piece of this design is to put the following code in your Post_ShowUI handler. This will call the Tooltip loader every time an applet is rendered.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfyffFTB5s9X0Zlf12UQSGNInIF9sdQW2CqhyQ5P-36H8JaKAETgawg3RmdCDehOj1a19UgrlpOA1f45_VAYzXO88rT3UVkheC_1su2S1LCfakfKHzXw-gtIPCb6iUQFaWwd3TlXGWxc8M/s1600/OUI_TT2_Post_ShowUI_Handler.png" imageanchor="1"><img border="0" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfyffFTB5s9X0Zlf12UQSGNInIF9sdQW2CqhyQ5P-36H8JaKAETgawg3RmdCDehOj1a19UgrlpOA1f45_VAYzXO88rT3UVkheC_1su2S1LCfakfKHzXw-gtIPCb6iUQFaWwd3TlXGWxc8M/s400/OUI_TT2_Post_ShowUI_Handler.png" width="400" /></a>
<br />
<br />
Now enjoy the fruits of our efforts.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6SakXU-ggWbeRCLpWOZy_CiusXrrS9TUF0EEooqFMIe991qBjr8M0S8DAaAhuVYpMs5zPZ6QM3EnUCPsRC6f6bzX3Q8GQUBwKhfXXTJPhtTyQ9dHJqCFnoQn6Q28CkyDpn4w75PyMhEtN/s1600/OUI_TT2_ListApplet_TT.png" imageanchor="1"><img border="0" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6SakXU-ggWbeRCLpWOZy_CiusXrrS9TUF0EEooqFMIe991qBjr8M0S8DAaAhuVYpMs5zPZ6QM3EnUCPsRC6f6bzX3Q8GQUBwKhfXXTJPhtTyQ9dHJqCFnoQn6Q28CkyDpn4w75PyMhEtN/s400/OUI_TT2_ListApplet_TT.png" width="400" /></a>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhTgrOVE0HG_dX5TuCplV9Z2RIiGqqXxZfxgqp3APb7ZRjFBRmBz3vUwqCF62Dr4WX7OvUB7CJCMvzT2p7XwaDe_X0Lp31q5y_WkRqEo0oB5Phas_aXhOdIaBcuLbtuxlBSH_WKX8PlAwM/s1600/OUI_TT2_FormApplet_TT.png" imageanchor="1"><img border="0" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhTgrOVE0HG_dX5TuCplV9Z2RIiGqqXxZfxgqp3APb7ZRjFBRmBz3vUwqCF62Dr4WX7OvUB7CJCMvzT2p7XwaDe_X0Lp31q5y_WkRqEo0oB5Phas_aXhOdIaBcuLbtuxlBSH_WKX8PlAwM/s400/OUI_TT2_FormApplet_TT.png" width="400" /></a>
<br />
<br />
Notice, that we have a little feel good icon to indicate to the user which Control/List have a Tooltip.
<br />
<b><br />Conclusion</b>
<br />
<br />
Tooltips are a lot easier to implement in Open UI, but it doesn’t mean that they are easy to implement. As with anything that is remotely complex in Siebel, there are two approaches one can take.
<br />
<br />
You can put on a builders hat, and say let’s create individual physical renders, hard code the tooltips into each file, and say job done in 5 minutes. This approach is cheap, but it has a nasty long term effect.
<br />
<br />
However if we put on our Architect hat, we will need to consider performance impacts, implement a server side script library, build client side libraries, and also satisfy custom requirements in a maintainable fashion. Not all of these issues have been addressed in this Article, but I’ve provided what I promised. An elegant Tooltips implementation in Open UI.<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com18tag:blogger.com,1999:blog-6992129293870658291.post-84686861512308904152013-08-05T20:35:00.001+10:002013-08-20T22:34:36.382+10:00Open UI: Property Set Methods (Fixing Copy)<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-new-structure.html">Open UI: New Property Set Structure</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-copy.html">Open UI: Property Set Methods (Copy, DeepCopy, Clone)</a> <br />
<a href="http://www.impossiblesiebel.com/2013/08/open-ui-property-set-methods-why-clone_20.html">Open UI: Property Set Methods (Why Clone?)</a>
<br />
<br />
In this article, we will look at the potential speed differences between Property Set methods Copy, DeepCopy and Clone. If we started from a clean Property Set, and used Copy, DeepCopy or Clone, to "copy" a Property Set, they would provide the same output and <i>could</i> be used interchangeably.
<br />
<br />
Just by looking at the function definition for Clone from the previous article, it is leaner, it doesn’t need to perform a Reset, or test for a null input, because Clone is called on an established Property Set, so in theory it will be the fastest. DeepCopy should perform just as fast as Clone for clean Property Sets.
<br />
<br />
The test case is to compare the run times for Copy, DeepCopy and Clone, using FireFox, IE and Chrome. The aim isn't to compare which browser is faster, but compare the methods relative to each other on the same browser. <br />
<br />
I've beefed up our previous test case to include 4 levels in the hierarchy, and run it with the results pictured below.
<br />
<br />
<pre class="brush:js">var ps=theApplication().NewPropertySet();
var psChild1=theApplication().NewPropertySet();
var psGrandChild1=theApplication().NewPropertySet();
var psGrandChild2=theApplication().NewPropertySet();
var psGrandChild3=theApplication().NewPropertySet();
var psGreatGrandChild1=theApplication().NewPropertySet();
var psChild2=theApplication().NewPropertySet();
ps.SetType("Parent");
ps.SetValue("ParentValue");
ps.SetProperty("Mum","Georgette");
ps.SetProperty("Dad","George");
psChild1.SetType("Child 1");
psChild1.SetProperty("Name","Bob");
psChild1.SetProperty("Gender","Male");
psGrandChild1.SetType("Grand Child 1");
psGrandChild1.SetProperty("Name","Bobby's Kid 1");
psGrandChild1.SetProperty("Gender","Male");
psGreatGrandChild1.SetType("Great Grand Child 1");
psGreatGrandChild1.SetProperty("Name","Bobby's Grand Kid 1");
psGreatGrandChild1.SetProperty("Gender","Male");
psGrandChild2.SetType("Grand Child 2");
psGrandChild2.SetProperty("Name","Bobby's Kid 2");
psGrandChild2.SetProperty("Gender","Male");
psChild2.SetType("Child 2");
psChild2.SetProperty("Name","Jane");
psChild2.SetProperty("Gender","Female");
psGrandChild3.SetType("Grand Child 3");
psGrandChild3.SetProperty("Name","Janes's Kid 2");
psGrandChild3.SetProperty("Gender","Male");
psGrandChild1.AddChild(psGreatGrandChild1);
psChild1.AddChild(psGrandChild1);
psChild1.AddChild(psGrandChild2);
psChild2.AddChild(psGrandChild3);
ps.AddChild(psChild1);
ps.AddChild(psChild2);
var psCopy=theApplication().NewPropertySet();
psCopy.Copy(ps);
console.log( "---------------------Copy Method---------------------\n"
+util.PSToStr(psCopy) );
var psClone=ps.Clone();
console.log( "---------------------Clone Method---------------------\n"
+util.PSToStr(psClone) );
var psDeepCopy=theApplication().NewPropertySet();
psDeepCopy.DeepCopy(ps);
console.log( "---------------------DeepCopy Method---------------------\n"
+util.PSToStr(psDeepCopy) );
</pre>
<br />
<br />
Results:
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVM3UmMQCQlUKw1eXRPgX51FILb83XAW1vpwI6Ubdhl0IUn2_swohe445Tphz1sUvLuu28C_xR32F3aNfgMDFILcgsMVL0GDdCHoQF_upzdZO3blZbyQcSP47xskNS8ag1v8jpeF7GvCKx/s1600/OUI_PS_Methods_Cp_DpCp_Clone_4_2_lvl.png" imageanchor="1"><img border="0" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVM3UmMQCQlUKw1eXRPgX51FILb83XAW1vpwI6Ubdhl0IUn2_swohe445Tphz1sUvLuu28C_xR32F3aNfgMDFILcgsMVL0GDdCHoQF_upzdZO3blZbyQcSP47xskNS8ag1v8jpeF7GvCKx/s400/OUI_PS_Methods_Cp_DpCp_Clone_4_2_lvl.png" width="400" /></a>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRrBQ-yhWaEUoiHm7sByGzgs_cLccLNw6ct-L6CLFmdgAuQR_VhOOIBY8BHNV2Phh6P5LDzdC_7T-XVCcuPv06vAm2UvBVJF3gzd60eHQUpG3FR2nSJ6fayuqkT-yEzg4txFajTGWT68tg/s1600/OUI_PS_Methods_Cp_DpCp_Clone_4_3_lvl.png" imageanchor="1"><img border="0" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRrBQ-yhWaEUoiHm7sByGzgs_cLccLNw6ct-L6CLFmdgAuQR_VhOOIBY8BHNV2Phh6P5LDzdC_7T-XVCcuPv06vAm2UvBVJF3gzd60eHQUpG3FR2nSJ6fayuqkT-yEzg4txFajTGWT68tg/s400/OUI_PS_Methods_Cp_DpCp_Clone_4_3_lvl.png" width="400" /></a>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY78w6BdamajqJi7nw7QjJOJHDN_mL8l5gIOexG_cskn9Q0VUUoA5cuZt9T9iaRoc0sj7H-tEeqwiDAOxS5wdV22lAA_Ih5M781ADCKYzcvWx7-PqcRGXVnz2-n5s3ko1lsmhI4AoqlWDP/s1600/OUI_PS_Methods_Cp_DpCp_Clone_4_1_lvl.png" imageanchor="1"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY78w6BdamajqJi7nw7QjJOJHDN_mL8l5gIOexG_cskn9Q0VUUoA5cuZt9T9iaRoc0sj7H-tEeqwiDAOxS5wdV22lAA_Ih5M781ADCKYzcvWx7-PqcRGXVnz2-n5s3ko1lsmhI4AoqlWDP/s400/OUI_PS_Methods_Cp_DpCp_Clone_4_1_lvl.png" width="400" /></a>
<br />
<br />
The results show something extraordinary with <b>Copy</b>, It looks like the recursion traverses the tree, and only the last Property Set of the children of the Parent nodes are returned.
<br />
<br />
Copy doesn't perform a full copy as we expected. To verify whether this has been broken in prior versions of Siebel, I ran the same test case in Siebel 8.1.1.5 HI, which does correctly copy the full Property Set, confirming the defect in 8.1.1.10.
<br />
<br />
To see why this is broken, we need to inspect the definition for Copy again.
<br />
<br />
<pre class="brush:js">function JSSPropertySet_Copy(old) {
var i;
var oldChild;
var name;
if (this.axObj != null) {
if (old == null)
return (false);
this.axObj.Copy(old.axObj); // this should return a value
return (true);
}
this.Reset();
if (old == null)
return (false);
name = old.GetType();
if (name != null && name != "")
this.SetType(name);
value = old.GetValue();
if (value != null && value != "")
this.SetValue(value);
for (name in old.propArray)
this.SetPropertyStr(name, old.propArray[name]);
for (i = 0; i < old.childArray.length; i++) {
oldChild = old.childArray[i];
if (oldChild == null)
break;
newChild = new JSSPropertySet();
newChild.Copy(oldChild);
this.AddChild(newChild);
}
return (true);
}
</pre>
<br />
<br />
The key area to focus on would be the for loop, and the recursion line <i>newChild.Copy(oldChild);</i>.
<br />
<br />
<pre class="brush:js">for (i = 0; i < old.childArray.length; i++) {
oldChild = old.childArray[i];
if (oldChild == null)
break;
newChild = new JSSPropertySet();
newChild.Copy(oldChild);
this.AddChild(newChild);
}
</pre>
<br />
<br />
An interesting thing to note is that the <b>newChild</b> variable is never declared in this function. Although this is generally considered bad practice, as it causes the variable to be created in Global scope, the Clone method uses this same technique, and it does function correctly.
<br />
<br />
The above block will loop through all the children of the parent, and perform the recursion at each children. This recursion design should work because, the children and all its children are passed into another Copy method, until all the descendants have been found, and returned back the parent.
<br />
<br />
The problem here is the use of that undeclared <b>newChild</b> variable, and this line <i>newChild = new JSSPropertySet();</i>.
<br />
<br />
The <b>newChild</b> Property Set is reset each time it iterates through a new child, therefore wiping out the parent Property Sets. The recursion will eventually finish at the last child, which is not necessarily the deepest.
<br />
<br />
This diagram shows how this flawed recursion will work.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs9Xy8VIUlxBkAkUxvxkw2I0MahuslFKa-VgzvH2FZowE0nIwsWGVzUmrQbaB-j6CZSXH3-wCzihLex6xIxNzrDfl2_cjUi3t23l4Sn-JuX4PSnis94jv2V_DVv4jZsA2-wuKUc1yK-kEP/s1600/OUI_PS_Methods_Fixing_Cp_run.png" imageanchor="1"><img border="0" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs9Xy8VIUlxBkAkUxvxkw2I0MahuslFKa-VgzvH2FZowE0nIwsWGVzUmrQbaB-j6CZSXH3-wCzihLex6xIxNzrDfl2_cjUi3t23l4Sn-JuX4PSnis94jv2V_DVv4jZsA2-wuKUc1yK-kEP/s400/OUI_PS_Methods_Fixing_Cp_run.png" width="400" /></a>
<br />
<br />
Points 1,2,3,4 shows the path that the recursion will take. The Property Set at points 1,2 will be clobbered by the statement <i>newChild = new JSSPropertySet();</i>. Only Property Sets 3 and 4 will actually make it out alive, as can be seen in the result above.
<br />
<br />
<b>Fixing Copy</b>
<br />
<br />
A simple fix is to declare <b>newChild</b> as a local variable as follows.
<br />
<br />
<pre class="brush:js">for (i = 0; i < old.childArray.length; i++) {
oldChild = old.childArray[i];
if (oldChild == null)
break;
var newChild = new JSSPropertySet();
newChild.Copy(oldChild);
this.AddChild(newChild);
}
</pre>
<br />
<br />
To test our fix, re-running our first test case again, shows this result.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuylv-wrR41zmJTjWMuAiqq7y5BEb1CoYsxdIMi-n9j-kSPPkwuCSIUnsLaw71vvnHkQsuZ00dziY3ZTPX0hosElbXpyqjiXsqV-OchtzDfpKcO6Y5L6W9oraJfRL1qQnheSLfs0gS8j5H/s1600/OUI_PS_Methods_Fixing_Cp_result.png" imageanchor="1"><img border="0" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuylv-wrR41zmJTjWMuAiqq7y5BEb1CoYsxdIMi-n9j-kSPPkwuCSIUnsLaw71vvnHkQsuZ00dziY3ZTPX0hosElbXpyqjiXsqV-OchtzDfpKcO6Y5L6W9oraJfRL1qQnheSLfs0gS8j5H/s400/OUI_PS_Methods_Fixing_Cp_result.png" width="400" /></a>
<br />
<br />
<b>Copy, DeepCopy, Clone times</b>
<br />
<br />
After putting that fix in, we can now reliably run the performance timings. Again, this is not a browser test, but a comparison of the speed difference between Copy, DeepCopy and Clone. I’ve had to run a lot less iterations in FireFox, and IE, to ensure the execution didn't time out the browser.
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi90ZzNunej0JOp_x80ud-voznI04PtdapVwdagt3mhgaOJK2cjCysKkO5mwB3QiVpD-IppuGTUzIBP1gObpvoPMz0Kn5WHJHtfJgjBi4FFInm2znunbsDS9Tlv3C0W4avO9vfgB7kje8Ks/s1600/OUI_PS_Methods_Fixing_Cp_Time_chart.png" imageanchor="1"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi90ZzNunej0JOp_x80ud-voznI04PtdapVwdagt3mhgaOJK2cjCysKkO5mwB3QiVpD-IppuGTUzIBP1gObpvoPMz0Kn5WHJHtfJgjBi4FFInm2znunbsDS9Tlv3C0W4avO9vfgB7kje8Ks/s640/OUI_PS_Methods_Fixing_Cp_Time_chart.png" width="496" /></a>
<br />
<br />
Result: In each graph, the baseline is represented by 0, which is the fastest function. The other columns represents, how slow the respective methods are compared to the baseline function.
<br />
<br />
<b>Summary</b>
<br />
<br />
<blockquote>
* Clone is faster in Chrome and IE, and only losing to DeepCopy by 3% in FF<br />
* There isn’t much different between DeepCopy and Clone in FF and IE<br />
* Copy is undoubtedly slower, being 22% slower than Clone in IE, 8% slower in FF, and 18% slower in Chrome
</blockquote>
<br />
<br />
The bottom line is that Copy is the slowest, the biggest difference will be seen if you have a massive hierarchy to Copy, or if you have to loop several thousand times, but for once off operations, you may see little practical difference. However, I would take any performance benefit where I can get, it if the effort is minuscule.
<br />
<br />
The fix we put in for this article is purely for educational purposes. I would recommend you use DeepCopy, and perform a Reset on the property beforehand, and wait until this is fixed officially by Siebel in future releases.
<br />
<br />
<b>The purpose of Clone</b>
<br />
<br />
Copy has been broken inadvertently, but Siebel would not design a new method with a different name to replace the broken one. Siebel would also not design a better performing function and give it a different name.
<br />
<br />
The inherent difference in the design of Copy/DeepCopy Vs Clone should provide a little clue to the purpose of Clone, does anyone want to speculate? The answer deserves an in-depth explanation, as it involves a fundamental misconception in Java Script/Browser Script/eScript.
<br />
<br />
I've tried hard to separate Copy, DeepCopy and Clone, but the mystery seems to get deeper the more we look. In the last article on these 3 methods I'll provide the definitive meaning of life for Clone.
<br />
<br />Jason Lehttp://www.blogger.com/profile/13322055780076477366noreply@blogger.com0