Server Scripting - fdlGitHub/ServiceNow GitHub Wiki

DEPRECEATED


Aggregate - addHaving function

var gr = new GlideAggregate('<table_name>');
gr.groupBy('<field_name>');
gr.addHaving('COUNT', '>', 1);
gr.query();
//Use gr.addHaving('COUNT', '>', 0); and !gr.next() when searching to know if a record is not present

Dot-Walking or getRefRecord

The dot-walking is deprecated. It was replaced by the getRefRecord() method.

To prevent performance issue (each dot-walking generate a SQL request) and to can validate an API before publish it into the Service Now Store, it's recommanded to use the getRefRecord method and to stock the result into a variable to be able to re-use it each time it's needed.

In the following example, current is a record of the Incident table

var callerGR = current.caller_id.getRefRecord();

gs.log('eMail address : ' + callerGR.email); // Instead of current.caller_id.email
gs.log('eMail address : ' + callerGR.vip); // Instead of current.caller_id.vip

ServiceNow Documentation : getRefRecord()


Large Query - Chunk result

var gr = new GlideRecord(<TABLE_NAME>);
// gr.query(); // This statement should never be used here while using the chunker. It's the chunker itself that will do it
var chunkGR = chunker(gr, 100, false);
while(chunkGR()) {
    while(gr.next()) {
        // Do something
    }
}

function chunker(gr, size, isDeleting) {
    var window_start = 0;
    var window_size = size;
    var chunkyGR = gr;
    return nextChunk;
    
    function nextChunk() {
        // Example: if window_start = 0 and window_size = 100, we need to remove 1 record to ensure that we are taking 100 tickets (0 to 99), else, we will take 101 tickets (0 to 100) and the 100 one will be take two times
        gr.chooseWindow(window_start, window_start + window_size - 1);
        gr.query();
        var has_next = (window_start < gr.getRowCount());
        // When we are doing a delete action, we don't need to increase the window_start
        if(!isDeleting) {
            window_start += window_size;
        }
        return has_next;
    }
}

Evaluate a script

The method eval(<STRING_TO_BE_EVALUATED>) is deprecated. It was replaced by the GlideScopedEvaluator object.

ServiceNow Documentation : GlideScopedEvaluator

var answer = '';
var evaluator = new GlideScopedEvaluator();

var parms = {};
parms.key1 = 'value1';

var gr = new GlideRecord('content_page_rule');
gr.get('46bbe1390a0a0b170039d28d0e7b9973');
// advanced_condition = gs.getUser().hasRoles();
answer = evaluator.evaluateScript(gr, 'advanced_condition', parms);

gs.info(answer); // true

Impersonate a user in a script

var currentUser = gs.getUserID();

try {
    // Replace <USER_SYS_ID> with the sys_id of the user you would like to impersonate
    gs.getSession().impersonate('<USER_SYS_ID>');
    
    // Do something
    
}
catch(ex) {
    gs.print(ex);
}
finally {
    // Go back to the previous user
    gs.getSession().impersonate(currentUser);
}

Check if user is impersonating

if (gs.getImpersonatingUserName() !== gs.getUserName() && gs.getImpersonatingUserName() !== null) {
    // Impersonate in progress, gs.hasRole('impersonator') is returning false
}

Check catalog visibility

To check visibility (user criteria) of categories and catalog items

GlideappCategory.get(CATEGORY_SYS_ID).canView()
GlideappCatalogItem.get(CAT_ITEM_SYS_ID).canView()

Tiny URL

To be used with sysparm_tiny

 var tinyUrl = new GlideTinyURL().createTinyURL(tableName + "_list.do?sysparm_query=sys_idIN" + sysIdList);
 return tinyUrl;

Date in any format

Format available here: https://docs.oracle.com/javase/10/docs/api/java/text/SimpleDateFormat.html

new GlideDate().getByFormat('dd.MM.yyyy HH:mm:ss.SSS')

Script Include : Multiple Inclusion

Declare your first Script Include (e.g : scriptLog)

var scriptLog= Class.create();
scriptLog.prototype = {
    enableDebug: function(value) {
        return value;
    },
    
    type: 'scriptLog'
};

Then declare a new one (e.g : scriptUtil)

var scriptUtil = Class.create();
scriptUtil.prototype = {
    _isUtil: function() {
        return false;
    },
    
    type: 'scriptUtil'
};

You are now able to declare the main Script Include with two first Script Include as extension

var mainScriptInclude = Class.create();
mainScriptInclude.prototype = Object.extendsObject(scriptLog, scriptUtil.prototype);
// mainScriptInclude have now methods of scriptLog and scriptUtil as local methods
// Extend again the mainScriptInclude by adding other methods
mainScriptInclude.prototype = Object.extendsObject(mainScriptInclude, {
    initialize: function() {
        gs.info('scriptLog method said : ' + this.enableDebug(true); // Result : true
        gs.info('scriptUtil method said : ' + this._isUtil()); // Result : false
    },
    
    process: function() {
        gs.info('Processing...');
    },
    
    type: 'mainScriptInclude'
});

It can be write as well like this:

var mainScriptInclude = Class.create();
mainScriptInclude.prototype = Object.extendsObject(scriptLog, {});
mainScriptInclude.prototype = Object.extendsObject(scriptUtil, mainScriptInclude.prototype);
// mainScriptInclude have now methods of scriptLog and scriptUtil as local methods
// Extend again the mainScriptInclude by adding other methods
mainScriptInclude.prototype = Object.extendsObject(mainScriptInclude, {
    initialize: function() {
        gs.info('scriptLog method said : ' + this.enableDebug(true); // Result : true
        gs.info('scriptUtil method said : ' + this._isUtil()); // Result : false
    },
    
    process: function() {
        gs.info('Processing...');
    },
    
    type: 'mainScriptInclude'
});

Force an update on record(s)

You can update records (run Business Rules) without updating a field. To do it, you need to use the setForceUpdate methog of the GlideRecord object.

Available only in the Global scope.

ServiceNow Documentation : setForceUpdate

// Replace <TABLE_NAME> by the name of a table (e.g : incident)
var tableGR = new GlideRecord('<TABLE_NAME>');
// Apply a query if necessary
tableGR.query();
while(tableGR.next()) {
    tableGR.setForceUpdate(true);
    tableGR.update();
}

Checking date against schedule

ServiceNow Documentation : IsInSchedule

var gdt = new GlideDateTime('2017-11-20 15:00:00');

var scheduleGS = new  GlideSchedule('<SYS_ID>');
var inSchedule = scheduleGS.isInSchedule(gdt);

Copy variables from a record to another one

After submitting the form, variables displayed into a record producer are stored into:

  • Questions Answers [question_answer] table for Task [task] (and inherited) tables
  • Variable Ownerships [sc_item_option_mtom] table for Catalog Services tables

Task tables

var questionAnswerGR = new GlideRecord('question_answer');
questionAnswerGR.addQuery('table_name', <table_name>);
questionAnswerGR.addQuery('table_sys_id', <sys_id>);
questionAnswerGR.query();
while(questionAnswerGR.next()) {
    questionAnswerGR.table_name = <new_table_name>;
    questionAnswerGR.table_sys_id = <new_sys_id>;
    questionAnswerGR.insert();
}

Base 64 - Encode/Decode values

The combo Username and Password can be or need to be encrypted like username:password. To encode/decode this syntax, use the following script:

Decoding

GlideStringUtil.base64Decode('<encoded_base64>')

Encoding

GlideStringUtil.base64Encode('<username:password>')

Decrypt password

To obtain the clear text value of Password (2 way encrypted) fields, use following script :

Global Scope

var encrypter = new GlideEncrypter();  
encrypter.decrypt(<Encrypted value>);

ServiceNow Documentation : GlideEncrypterAPI

Application Scope

Replace <Field_Name> by the password field name whom you want have

gr.<Field_Name>.getDecryptedValue()

ServiceNow Documentation : GetDecryptedValue


URL - Use another field as sys_id

By using the sysparm_refkey parameter into a URL, you can open the form of a record by using another key than the sys_id

https://instancename.service-now.com/sys_dictionary.do?sys_id=assignmentgroup&sysparm_refkey=element

URL - Open JSON view

By using the specified URL, you can open the JSON view

https://instancename.service-now.com/TABLE_NAME.do?sysparm_sys_id=SYS_ID&sysparm_target=u_response_body&sysparm_action=getRecordColumn&JSONv2=

Force a Scheduled Job to run on a node

Be careful: Once the job is finished, the system will create, based on the Scheduled Job Definition, a new "Today's Scheduled Job" (sys_trigger) and will keep it assigned to the node. To make sure that this job will not get stuck at some point (node offline, clone not cleaning properly the job, ...), don't forget to clear the system_id field.

var triggerGR = new GlideRecord('sys_trigger');
triggerGR.get('TRIGGER_SYS_ID');
triggerGR.system_id = 'SERVER_NAME_NODE_NAME';
triggerGR.update();

Import XML file

Be careful: Method not documented by ServiceNow, so not supported!

var streamLoader = new GlideStreamLoader();
streamLoader.loadXML('<xml><unload format></unload format>');

Get node info

Be careful: Method not documented by ServiceNow, so not supported!

GlideProperties.get("glide.cluster.node_name") => name of the node
gs.getNodeID() => sys_id of the node
gs.getSystemID() => server:node name

Get Java version

Be careful: Method not documented by ServiceNow, so not supported!

gs.getJavaVersion()

Database Aliases

Database aliases are stored into sys_storage_table_alias for tables.

Database aliases are stored into sys_storage_alias for fields.


Refresh Table Cache

Following script has to be executed as a background script on one node; it will automatically flush the cache of all other application nodes

GlideTableManager.invalidateTable('table_name');
GlideCacheManager.flushTable('table_name');

Documentation: KB0695145 - Table alters via update set sometimes do not invalidate cache correctly on other nodes

DEPRECEATED


Move field from Parent table to Child table

Be careful: Method not documented by ServiceNow, so not supported! NO LONGER USABLE SINCE LONDON

GlideDBUtil.promoteColumn('cmdb_ci', 'cmdb_ci_service', 'u_yourfield', false);

Documentation: Moving a column from a parent table to an extended table

ServiceNow Documentation: Move a field from a child to a parent table does not work with promoteColumn()


Move field from Child table to Parent table

Be careful: Method not documented by ServiceNow, so not supported! NO LONGER USABLE SINCE LONDON

GlideDBUtil.promoteColumn('cmdb_ci_service', 'cmdb_ci', 'u_yourfield', true);

Documentation: Promote a Field from an Extended Table in ServiceNow

ServiceNow Documentation: Move a field from a child to a parent table does not work with promoteColumn()

⚠️ **GitHub.com Fallback** ⚠️