In this article, we'll do a scriptless PreSetFieldValue validation as an alternative solution to field-level validation. Clearly, PreSetFieldValue is not always the best fit for user input validations. But when you've been given no choice, here is a declarative and scalable solution to consider.


Background


We'll be using a well-known stack: RunTime Events (RTE) + Data Validation Manager (DVM). And I'll also show you some tricks to work around the limitations.

The first challenge is to fetch a new field value. As you know at the PreSetFieldValue event BusComp holds an original value. Here is a couple of Siebel Support articles explaining the problem:

The solution is in the implicit parameter that runtime event passes by to a business service. And this parameter is [PreSetFieldValue]. Separate thanks to Jason for the hint!

Parameter Description
Object Name The name of the object experiencing the event
Event Type The type of object (BusComp, Applet, Application)
ActionSet The name of the action set
EventId The ROW_ID of the event
Sub Event The content of the Sub Event field (method, field, view name)
Action The name of the action
Event Name The name of the event such as PreWriteRecord, InvokeMethod etc
Context The content of the Business Service Context field. Alex has a great article on how to take an advantage of it.
Business Component Name An active BucComp name. Only available when [Object Type] = "Applet" or "BusComp"
PreSetFieldValue A new field value. Only available when [Event] = "PreSetFieldValue"
There are probably other event-specific parameters out there

Next problem is that the DVM business service can't handle implicit RTE parameters. I presume since DVM business service handles the Context parameter natively, it probably replaces the implicit inputs PropertySet with the new one constructed from the Context parameter.

Anyway, it shouldn't stop us. We can call another BS that accepts RTE parameters and converts them into profile attributes(PA) and then we can use the PA in the DVM rule. Feel free to create your generic BS which converts input parameter(s) into profile attribute(s) or use [User Registration] business service.


Case study


Imagine you've been asked to ensure [Account.Close Reason] is provided when you set [Account.Status] = 'Closed' and presumably locking the record.

So, let's start with creating a Runtime ActionSet "Account Close Reason Validation" with two actions as below:

Sequence Action Type Business Service Name Business Service Method Business Service Context
1 BusService User Registration SetProfileAttr  
2 BusService Data Validation Manager Validate RuleSet,Account Close Reason Validation

Now we can create a Runtime Event:

Object Type Object Name Event Subevent Action Set Name
BusComp Account PreSetFieldValue Status Account Close Reason Validation

And finally a DVM RuleSet with one rule:

Name Stop On Error Immediate Display Rule Expression
Account Close Reason Validation Y Y GetProfileAttr("PreSetFieldValue") <> "Closed" OR [Close Reason] IS NOT NULL

Done! Another scriptless solution in your toolbox!

P.S.: Beware that GetPofileAttr function always returns string. To retrieve other data types, please use type specific functions.

Starting a series "Runtime objects cache". And the first runtime object I'll be covering is Runtime Events (RTE).

Background:

If you are working with RTE you probably know about "Reload Runtime Events" menu command, which allows you to clear RTE cache in your current session. But, what if you are working with multiple sessions? For example, doing your configuration under one user / application and testing it under another, where you don't have access to RTE screen. It could also be a case where you don't want to lose a context. And finally, you might be creating RTE indirectly, from workflows start connector. It all leads you to restarting a Siebel client or losing a context.

Solution:

It turns out "Reload Runtime Events" command is an implicit BC method supported by generic CSSBusComp class. It means we can run that command from any applet and let it propagate to BC. Thanks to Siebel OUI we can run any applet method right from the browser console. As simple as that:

SiebelApp.S_App.GetActiveView().GetActiveApplet().InvokeMethod("ClearCTEventCache");

Here I've made a bookmarklet out of it, so you can run Reload RTE command from browsers bookmark toolbar in any application/view/context without any pre-configuration:

  • Source code: Snippet
  • /* 
    @desc Reloads Runtime Events
    @author VB(xapuk.com)
    @version 1.1 2019/04/20
    */
    if("undefined" === typeof SiebelApp){
        alert("Please, log into Siebel application first!");
    }else{
        var v = SiebelApp.S_App.GetActiveView();
        var ap = v.GetActiveApplet();
        if ("undefined" === typeof ap) {
            ap = v.GetAppletMap()[Object.keys(v.GetAppletMap())[0]];
        }
        if ("undefined" === typeof ap) {
            alert("No applet found!");
        } else {
            ap.InvokeMethod("ClearCTEventCache", null, {
                "cb": function(e) {
                    alert("Runtime Events were reloaded!");
                },
                "errcb": function(e) {
                    console.log("Err", e);
                    alert(e.toString());
                }
            });
        }
    }
    
  • Bookmarklet code: Snippet
  • javascript:void function(){if("undefined"==typeof SiebelApp)alert("Please, log into Siebel application first!");else{var e=SiebelApp.S_App.GetActiveView(),t=e.GetActiveApplet();"undefined"==typeof t&&(t=e.GetAppletMap()[Object.keys(e.GetAppletMap())[0]]),"undefined"==typeof t?alert("No applet found!"):t.InvokeMethod("ClearCTEventCache",null,{cb:function(e){alert("Runtime Events were reloaded!")},errcb:function(e){console.log("Err",e),alert(e.toString())}})}}();
    
  • Bookmark link: Drag&drop me

Bonus:

You can use the same approach to reset List of Values cache:

SiebelApp.S_App.GetActiveView().GetActiveApplet().InvokeMethod("ClearLOVCache");

 

and View/Responsibility cache:

SiebelApp.S_App.GetActiveView().GetActiveApplet().InvokeMethod("ClearResponsibilityCache");