Dot-walking is well-known among ServiceNow enthusiasts for its simplicity in accessing elements across referenced records. However, simplicity isn’t always the best approach. If you haven’t encountered dot-walking failures in some scenarios, have you really delved deep into ServiceNow scripting? It’s been a while since I almost completely stopped using dot-walking to read values, opting instead for the many GlideRecord and GlideElement functions. Let’s discuss a flaw of dot-walking that have led me to move away from it.
General syntax
var sys_id = 'sys_id of some incident record';
var incGr = new GlideRecord('incident');
incGr.get(sys_id);
gs.info('Caller sys_id : ' + incGr.caller_id);
gs.info('Caller name : ' + incGr.caller_id.name);
The problem
Dot-walking returns ‘objects’
When we try to execute the below snippet in a background script,
var sys_id = 'sys_id of some incident record';
var incGr = new GlideRecord('incident');
incGr.get(sys_id);
gs.info(typeof(incGr.caller_id.name));
we get an output like –
If we add another line to the snippet,
gs.info(incGr.caller_id.name);
we get an output like –
What does this tell us about GlideRecord? It is trying to objectify our George Warren here. But does George look like an object? Not to me they don’t.
So if we are able to get the name printed even if it is classified as an object, where exactly is the problem? Let’s look further.
When we try to execute the below snippet in a background script,
var sys_id = 'sys_id of some incident record';
var incGr = new GlideRecord('incident');
incGr.get(sys_id);
if (incGr.caller_id.name == 'George Warren') {
gs.info('George is a string.');
} else {
gs.info('George is an object.');
}
we get an output like –
But if we execute the below snippet instead,
var sys_id = 'sys_id of some incident record';
var incGr = new GlideRecord('incident');
incGr.get(sys_id);
if (incGr.caller_id.name === 'George Warren') {
gs.info('George is a string.');
} else {
gs.info('George is an object.');
}
the output turns out to be –
Woah, wait, what just happened?
- the second snippet had an extra ‘=’.
Why would that make a difference?
- well, == performs type conversion if needed and returns true if the operands have the same value after conversion, otherwise, it returns false. === does not perform type conversion and returns true only if both operands are of the same data type and have the same value, otherwise, it returns false.
So, to conclude, dot-walking returns objects, and objects are not as friendly as a string (or any other natural data type like integer, boolean, etc).
The fix
Become an avid user of the various GlideRecord and GlideElement functions. There is a function available for almost every requirement. Below are a few functions that I religiously use to keep my code clean and error free.
getUniqueValue()
Ditched
incGr.sys_id
and started using
incGr.getUniqueValue()
getValue(String name)
Ditched
incGr.caller_id
and started using
incGr.getValue('caller_id')
getDisplayValue()
Ditched
incGr.caller_id.name
and started using
incGr.getDisplayValue('caller_id')
getTableName()
Ditched
incGr.sys_class_name
and started using
incGr.getTableName()
getRefRecord() – favourite
Ditched
var caller = new GlideRecord('sys_user');
caller.addQuery('sys_id', incGr.caller_id);
caller.query();
/* can also be caller.get(incGr.caller_id)
but that is not the point */
if (caller.next()) {
gs.info(caller.email);
gs.info(caller.title);
}
and ditched
incGr.caller_id.email
incGr.caller_id.title
...
started using
var caller = incGr.caller_id.getRefRecord();
if (caller.isValidRecord()) {
gs.info(caller.getValue('email'));
gs.info(caller.getValue('title'));
}
and started using
incGr.caller_id.getRefRecord().getValue('email')
and numerous other OOB functions for
Next steps
Aim to instil a habit of using such functions in our script implementations and ensure that our fellow coders adopt this practice as well. If ServiceNow is our life, these habits will just make it easier.
Insightful
nice article and articulation