Why not to mix Java and JavaScript types in ServiceNow®

Often customer hire me and soon they say “our instance has some hiccups now and then” — or I try to develop something and stumble over hard to reproduce bugs. As I dig deeper, I find a strange behaviours or parts of the system… I call them the quirks of ServiceNow®.

A text field in ServiceNow is a String, a String and a GlideElement

var grUser = new GlideRecord('sys_user'); 
grUser.get('6816f79cc0a8016401c5a33be04be441'); // sys_id of the default admin user 

// ------------------------------------------------------------------------

gs.print("---");
gs.print(grUser.title instanceof GlideElement);              //==> true
gs.print(grUser.title instanceof Packages.java.lang.String); //==> true
gs.print(grUser.title instanceof String);                    //==> false
gs.print("---");
gs.print(typeof grUser.title);                               //==> object
gs.print(typeof grUser.title.toUpperCase);                   //==> function
gs.print(typeof (grUser.title +'').toUpperCase);             //==> function
gs.print(grUser.title);                                      //==> System Administrator
gs.print(grUser.title +'');                                  //==> System Administrator
gs.print("");

// -------------------------------------------------------------------------

// City is empty (city.nil() == true)
gs.print(grUser.city instanceof GlideElement);              //==> true
gs.print(grUser.city instanceof Packages.java.lang.String); //==> true 
gs.print(grUser.city instanceof String);                    //==> false
gs.print("---");
gs.print(typeof grUser.city);                               //==> object 
gs.print(typeof grUser.city.toUpperCase);                   //==> undefined 
gs.print(typeof (grUser.city +'').toUpperCase);             //==> function
gs.print(grUser.city);                                      //==> 
gs.print(grUser.city +'');                                  //==> 
gs.print("");

How to avoid

After I discovered that mixing Java and JavaScript object types may cause problems — especially when comparing them or if a field is empty —, I now do indirect type casts… this prevents future mixing of (incompatible) types and ensures, the source code completely follows the ECMAScript standard as all parts are handled by the JavaScript engine rather than a mixture of JavaScript engine and the Java Interpreter.

Examples on how to avoid:

(grUser.city +'')
(+grIncident.state)
(grIncident.state *1)

Any further quirks?

You have encounters of the third kind as well? Just contact me at hello@cbc-faruhn.com so that we can share them here.