Synchronization Business Rule help

WilliamHazelrig
Giga Contributor

I've created a table parallel to cmn_location to permit the creation of aliases for locations. The business rule below is supposed to maintain a parallel hierarchy by creating a "canonical" alias (alias == name) for each Location and maintaining these records in parallel with changes to the cmn_location table. A separate rule runs on insert to u_bhs_location_aliases to set u_parent in the u_bhs_location_alias record appropriately (i.e. to the canonical alias of the corresponding location record's parent).

Unfortunately, it isn't working; when new records are inserted into cmn_location, no records are getting inserted into u_bhs_location_alias. While I've had more than a decade of JavaScript experience, I'm quite new to Service-Now; am I doing something obviously wrong, here (see attached)?

3 REPLIES 3

benn23
ServiceNow Employee
ServiceNow Employee

I changed a couple of things in your function... This should steer you in the right direction... Keep in mind the 'aliasRec.query' and 'if(aliasRec.next())' are case sensitive (the 'next' and 'query')... Also your 'setValues' should be handled a bit differently (shown below).
Hope this helps.

function maintainCanonicalAlias()
{ var aliasRec = new GlideRecord('u_bhs_location_aliases');
aliasRec.addQuery('u_location_alias',current.getDisplayValue());
aliasRec.query();
if (aliasRec.next()) // found existing Alias; update it accordingly:
{ aliasRec.u_location=current.sys_id;
aliasRec.u_parent=current.parent.u_canonical_alias.sys_id;
aliasRec.update();
}
else // no existing Alias; create one accordingly:
{ aliasRec = new GlideRecord('u_bhs_location_aliases');
aliasRec.initialize();
aliasRec.u_location_alias=current.getDisplayValue();
aliasRec.u_location=current.sys_id;
if (current.u_parent != '')
{ aliasRec.u_parent=current.parent.u_canonical_alias.sys_id; }
aliasRec.insert();
} // end "if (aliasRec.Next()) ... else ..."

current.u_canonical_alias = aliasRec.sys_id;
current.update();
}


WilliamHazelrig
Giga Contributor

Thank you. I'd actually tried that approach first but changed it when I found that the Business Rule didn't work. I managed to determine experimentally tonight where the actual problem lay, thanks to some help from http://wiki.service-now.com/index.php?title=Scripting_Alert,_Info,_and_Error_Messages:

/* This function does not work */
function relevantUpdates()
{ if (current.operation() == "insert")
{ return true; }
else if (current.getDisplayValue() != previous.getDisplayValue())
{ return true; }
else if (current.parent != previous.parent)
{ return true; }
else
{ return false; }
}
/* Reason for failure: in the "after" context, current.operation() returns nil and previous is either a clone of or the same object as current. I've posted a comment requesting that this be noted in http://wiki.service-now.com/index.php?title=Business_Rules#Business_Rule_Scripting, where the use of the "previous" variable is documented. I presume both "previous" and "current.operation()" do work as advertised in the "before" context, but I haven't tested it.
*/

I took out the "if" and reverted the code for maintainCanonicalAlias() back to the cleaner dot-walking operations and use of the javascript assignment operator; it works nicely now.


WilliamHazelrig
Giga Contributor

Just a note to the community:
Because of the availability of the ref_ac_columns attribute, we retired this approach very early in our build and put the aliases in a run-on large text field. It's not as logical a solution as a table of distinct alias entries, but it proved to be much simpler to implement and maintain.