Don’t Loose Your Precious Data

I’m sure if the team at the SiebelHub would in their series of ‘snap polls‘ start another poll soliciting for the top most UX ‘inconveniences’ with Siebel OpenUI, will find among the higher ranking  issues the fact that the ‘back button’ should be used with great care.

Great care, because any uncommitted data will be gone, forever. Have you just spent half an hour on a lengthy call report? The back button will not commit it for you, rather will throw it away… This very issue comes up again and again.

Although there is no water-tight solution, I have been testing a feasible approach using the undocumented method ‘IsCommitPending’. I found that this method of the business component class tells you whether there is in-flight data.

Just entering following on the browser’s console will tell you, if you have in-flight data:

SiebelApp.S_App.GetActiveView().GetActiveApplet().GetBusComp().IsCommitPending();

That’s actually a pretty cool framework feature, though… undocumented (hence it might change, and don’t try to ask Oracle tech support to provide further guidance…)

The IsCommitPending() returns a consistent output. Once you change any data, it will return ‘true’. The moment you either explicitly commit the data using CTRL+S or the applet menu ‘Save Record’, instantaneously IsCommitPending() will return ‘false’. Also stepping of a record, will implicitly commit the data, hence IsCommitPending() will return ‘false’ too.

So, I marched on. I created a simple applet presentation model as proof of concept to capture all ‘FieldChange’ events. On the first ‘FieldChange’ event I create a floating div with the id=datalossWarning and the default class ‘dataloss-warning-disabled’.

Per CSS pseudo-selector I add a font from the ‘oracle’ font, to serve as indicator.

checkred

I further attach a click event, which as part of this proof of concept I added to the presentation model as well. But rather, this should belong in a physical renderer instead… And rather than using the JQuery’s click event, it would be more appropriate to use the Helper class to make behavior consistent across non-touch and touch devices. But that is all for later!

Once the visual check box indicator appears, clicking the same will execute a write record as such:

SiebelApp.S_App.GetActiveView().GetActiveApplet().InvokeMethod(“WriteRecord”);

I choose to make it fade away using a simple transition. The CSS is as simple as effective.

datalosscss

The most relevant lines from the presentation model are presented below. Again, a setTimeout was required to ensure the code to be executed after all other framework code completed. Required to have the IsCommitPending() call to  return the correct value. Inspecting the value, drives simply swapping the CSS class from ‘dataloss-warning-disabled’ to ‘dataloss-warning-enabled’ or vice versa.

datalosscommitpending

The complete presentation model ‘CheckCommitPendingPM’ code for a list applet, is not more than a few lines besides the typical framework code required for any presentation model. I choose to use the ‘Init’ event, but likely the ‘Setup’ would have worked as well. Not sure if there is a benefit for either.

datalosscompletepm

I further added a few lines in my existing post loader, to remove the #datalossWarning div every time a new views loads.

datalosscommitpendingpostload

A brief demonstration puts the cherry on the cake:

Again, this is a proof of concept. Interested to hear feedback 🙂

As from previous readings, you might know that enabling this across the application is due a current framework limitation not that straightforward without possible breaking out of the box functionality. Simply overriding the ‘DEFAULT LIST APPLET’ presentation model, will due to the sequence in which the OpenUI framework loads code will prevent a possible out of the box presentation model to load. So be careful there!

–  Jeroen

 

 

 

 

 

 

Catch Those Uncaught Exceptions From Your Browser In Open UI – Part II

bugsnag-logo-1A few weeks back I posted an initial article about my experiences with Bugsnag. On a quest to get more insight in ‘what happens in the browser’, because by and large ‘what happens in the browser, stays in the browser’ I bumped into this neat tool. In this space of error reporting and incident management tools, alternatives exists such as Airbrake, Sentry, Rollbar and Raygun to name a few. I choose for a proof of concept Bugsnag because it appeared to be simple to integrate as well as it’s offered as 100% free trial.

Deploying complex web applications such as Siebel which are built on top of a bundled set of libraries such as JQuery, RequireJS and CKEditor poses a real challenge. Add the diversity of browsers in the mix, and you have a nice cocktail. Just the believe that functionality will work cross-browser is an utopia. Gaining the insight in ‘what happens in the browser’ can be considered a must-have, especially in a diverse environment where Siebel is exposed on different browsers, platforms, devices, in managed desktop environments or to users in the uncontrolled big, bad, world out there.

Setting up your trial account with Bugsnag requires just a few clicks. In return you will be provided an API key and access to your own Bugsnag dashoard.

The Bugsnag ‘notifier’ library is available to be integrated in any web application. Integrating it with Siebel turned out to be extremely simple. Just adding the library as ‘Application’ / ‘Common’ did the job. Setting the apiKey followed by invoking the notify() function in the console is enough to test the essentials.

Bugsnag.apiKey = “d31fd6cda4a46a9f4e251207c8xxxxxx”;

Bugsnag.notify(“SBL-ERR-BUGSNAG”, “Log this error”);

Logging onto your Bugsnag dashboard should show within the blink of an eye the error!

SBL-ERR-BUGSNAG

Nice. But we need to do better!

When Bugsnag intercepts an uncaught exception, it would be useful to have some contextual information being sent alongside the call stack, won’t it? For that particular purpose, the Bugsnag API allows to add ‘meta data’ by using the ‘beforeNotify’ function.

I ended up with a straight-forward piece of code, which loads as Application / Common file.

  1. It creates a new class ‘SiebelBugSnagNotifier’
  2. Next it creates a dependency on the Bugsnag Javascript API (‘bugsnag-2.min.js’)
  3. Following the apiKey is set (I opted for sake of simplicity to hard-code the key…)
  4. Next the beforeNotify() function is implemented
  5. The ‘metaData’ and ‘user’ JSON objects are populated with contextual information. Other than essential static details such as Login Name, User Responsibilities, View Name & Title – I added also the raw data (if available) from the applet which had focus the moment the exception got caught.

bugsnagnotifier

Now, what happens when I on-purpose generate an uncaught exception? Well, first of all we get a nice call stack leading quickly to the error. And yes, I made a type calling ‘setTimeout’ in the /siebel/custom/CheckCommitPendingPR.js!

samplestack

Further, the view context gets provided…

details3

As well as the raw data…

details2

And the logged in user details too…

details1

All together, quite happy with the end-result. And other than logging uncaught exceptions, calling Bugsnag.notify() anywhere in your code, could be an alternative for SiebelJS.Log(). But use it sparsely in that case, since it will definitely incur overhead. And we do not want to slow-down Siebel, do we?

You can grab the code here. If you have thoughts, let me know.

– Jeroen