A question on the Oracle discussion forum last week prompted me to dig out a MetaLink article that I’ve never noted here. The question was “How to call a local executable from the browser”: the answer is to use browser script to instantiate a Windows Scripting Host ‘Shell’ ActiveX object, like so:
var objWSH = new ActiveXObject("WScript.Shell");
objWSH.Run("notepad.exe");
More detail on using the ActiveXObject is available in the post on Client-side DLLS.
May 5th, 2008
I’ve mentioned previously that Siebel’s handling of phone numbers can cause havoc for EAI. The post on International Phone Formats outlines how Siebel stores phone numbers as a continuous string including the country code (+610298767654), appending a new line and format string to store special formats (+61041234567890<CR><LF>0000 0000 0000).
This fancy footwork works nicely in the UI, (mostly) displaying numbers in the expected format for the current country. However, imagine a standard Integration Object defined on business component Account, with a component field mapped to the Main Phone Number . Invoke an EAI Siebel Adapter Query for this integration object and the phone number result will be the database value - rather awkwardly including that unpleasant format string.
In older versions of Siebel, the only way around this ‘feature’ was to pass the integration object through a custom business service, stripping those format strings and rendering the phone number as desired: effectively, re-coding the function that Siebel apply at the UI. This was a pain.
Fortunately, Siebel 7.8 saw the introduction of the Integration Object User Property UseFormattedValues to force the EAI Siebel Adapter to use formatted values. If we add this undocumented user property to our Account Integration Object and set the value to Y, then the Siebel Adapter uses formatted values and Main Phone Number will contain exactly what you see in the UI. This eases the pain nicely.
If you’re more familiar with Siebel Scripting, this UseFormattedValues property forces the EAI Adapter to use Get/SetFormattedFieldValue-type requests, rather than Get/SetFieldValue. One restriction is that the User Property can only be applied to the whole Integration Object, not to individual fields - the property doesn’t work as an Integration Object Component User Property, nor as an Integration Object Component Field User Property. That’d be a feature request for future versions…
MetaLink mentions of UseFormattedValues are sparse, but there is a thin definition, plus a complaint about the inbound error handling.
April 29th, 2008
SKV commented on my Order of Events post from July pointing out a contradiction he spotted in TechNote 581. On page 20 of that document, point 4. states:
Problem: If a buscomp has code on WriteRecord and the runtime event fires on WriteRecord, which occurs first?
Solution: WriteRecord runtime event is in essence a Post-WriteRecord event and will be fired AFTER the buscomp code is executed.
That statement’s in direct opposition to my assertion that:
…the Runtime Event occurs before the equivalent Server Script event for the same object…
As I responded in the comments, this highlights a mantra I’ve learnt through painful experience: never trust the documentation! However, since my writing here is really just more documentation, it might be useful to explain how I arrived at my list. To get the order of events published previously, I took a random object (BusComp Account Note, as it happens) and modified each browser script and server script event to log the event to a file. For example, the PreWrite looks like this:
function BusComp_PreWriteRecord ()
{
var f = Clib.fopen("C:\\events.txt", "at");
Clib.fputs("BusComp_PreWriteRecord\n", f);
Clib.fclose(f)
f = null;
return (ContinueOperation);
}
A similar script on each event gives me an ordered list of script events. To add in the Runtime Events, I created a client-side business service to log to the same file. So in Admistration - Business Service > Details I created the Events business service, then added the Log method using a very similar script. This Log method takes a single parameter: the event string, which is appended to the file. In Administration - Runtime Events > Events, I can now add every event I want to log, with an action for each to call the Events.Log method with the name of the event. In no time at all, I have a complete, ordered list of events, as published. Given my testing, I’m inclined to assume the documentation is incorrect. However, all of my testing was only on Siebel 7.8, so there’s a slim chance of variations between versions. Anyone want to verify?
March 30th, 2008
I had a problem the other day where I needed to share a value between two applets. On a form applet there’s a browser script method that executes on the WriteRecord event, but it’s designed to only fire if certain other events have already run. To control the ’state’ (execute or not), there’s a boolean variable declared in the general declarations of the browser script. This form is used in a number of different views and works as designed.
The challenge was in the screen’s List view: here we have the form applet, which works as elsewhere, but also a list applet for the same business component. The behaviour should be the same for both applets. Easy enough, I figured: just copy the form’s browser script across to the list. And this approach appeared to work well enough.
An alert tester picked up the gap: if the operation was started in the list applet, but then completed in the form applet (or vice-versa), then the browser script wasn’t executing. In the first applet the state variable was set, but in the second applet not. What I needed was for the state to be shared across the two applets.
The usual way to share variables across objects is to use Profile Attributes or Global Variables, but neither solution was an option. Global variables simply aren’t available through browser scripts, while the getting and setting of profile attributes requires a round-trip to the server - too much of an overhead in this case. I thought I was going to have to resort to some sort of hidden control and FindApplet then FindControl methods, but the solution was much simpler.
Turns out that variables declared in the general declarations section of Browser Script are shared for all the applets in the view. Who knew? (See the note about halfway down.) Okay, quite possibly everyone except me, but now I won’t forget.
For my little problem, I was able to prescribe that this list applet be only used alongside the form applet, which meant that in the list’s browser script I could simply set and get state using the form’s variable. The applets now share state and everything works as expected.
March 27th, 2008
Okay, time for a rant. This is bugging me.
I spend a lot of time with Workflow: EAI work kind of forces that on you. Any moderately complicated workflow process always ends up needing a stack of workflow process properties. The vanilla processes Siebel provide are good examples of this phenomenon. This is understandable, and equivalent to a scripted function justifiably defining a bunch of local variables. So here’s the thing: when working with processes, why do I always see all the process properties defined to be ‘In/Out’? This is equivalent to a scripted function putting every local variable into the function definition. Crazy talk!
For those who don’t know, the In/Out parameter on a process property defines the purpose of the property. The values are In for input properties, Out for outputs, In/Out (the default) for properties that both accept and return a value, and None for those variables just used internally by the process. Pretty clear cut. Setting this parameter properly makes the workflow easier to understand - particularly helping when calling the workflow as a sub-process. Leaving it as the default In/Out value is lazy config, and I’ve seen too much of it. So there. Someone pass the message on to the developers inside Siebel, please.
P.S. While we’re at it: how about using process property types other than ‘String’ and ‘Hierarchy’ - and that ‘Integration Object’ parameter is pretty useful too…
March 3rd, 2008
Previous Posts