Scripting Overview

What, Why, When, Where, Who and How?

What is Platform Scripting: When making changes to you instance, use the Conditional Builder whenever possible to configure simple conditions and actions. However use Platform Scripting for complex configurations and behaviors via JavaScript.
Why Should You Not Script: ServiceNow is continually evolving, what you scripted in the past might not need to be scripted now. Consider ways of customizing without scripting.
When Should you Script:

  • Add new functionality
  • Extend existing functionality
  • Guide users through messaging
  • Automate processes
  • Interact with third-party applications

Where Do Scripts Execute:

  • Client Side
  • Server Side
  • MID Server

Who can Script: Generally admins, and selected roles.
How Do You Script: Using Syntax Editor, a built-in text editor.

Syntax Editor:

  • Context-Sensitive Help
  • Context Menu
    • Show Definition
    • Show Data
    • Find References
    • Open Definition
    • Show Documentation
  • The Syntax Editor:
    • Formatter
    • Comment / Uncomment
    • Macros System Definition > Syntax Editor Macros

Application Scope: Every application has a scope, determines which of its resources are available to other applications. Once a scope is assigned to an application, it cannot be changed. Explicit permission must be granted for applications to share their resources with other applications.
Scope protects an application and its artifacts from damage to or from other application. Artifacts are the application files in an application. Examples include tables, ACLs, Email Notifications.
All scoped application artifacts always begin with x_

JavaScript APIs:

Client-side ClassesServer-side Classes
GlideAjaxGlideAggregate
GlideFormGlideDateTime
GlideListGlideElement
GlideRecordGlideRecord
GlideUserGlideQuery
spModalGlideSystem
JSON
Workflow

For API documentation visit here

JavaScript Modes:

  • Compatibility Mode
  • ES5 Standards Mode
  • ECMAScript 2021 (ES12)

Client Scripts

Overview

Client Script: It manages the behavior of forms, fields and lists in real time. Executed on the client-side. There are more than 1600 client scripts in baseline implementation of ServiceNow.

System Definition > Client Scripts

Every Script contains:

  • Trigger
  • Description
  • Messages
  • Script

Trigger: Type field on the client script form

  • onLoad
  • onSubmit
  • onChange
  • onCellEdit

OnLoad: Runs when a form loads and before control is given to the user. Typically used to manipulate a form’s appearance.
OnSubmit: runs when a form is saved, updated or submitted. Typically used for field validation. If the input the user submits do not make sense, an onSubmit() client script can cancel form submission by returning a value of false:

OnLoad only runs if the page is reloaded after a save.

OnChange: Runs when a particular field value changes. Typically used to respond to field values of interest and modify one field value in response to another. An onChange() client script watches one field. If two fields need to be watched, a second client script must be configured.
It specifies these parameters:

  • control
  • oldValue
  • newValue
  • isLoading
  • isTemplate

OnCellEdit: It’s used when changes are done through lists. They do not apply to List Widgets on homepages or dashboards. You must return either true of false to allow the changes to the fields.
Parameters passed to onCellEdit():

  • sysIDs
  • table
  • oldValues
  • newValue
  • callback

Client-side APIs

Most popular client side APIs:

  • g_form (GlideForm)
  • g_user (GlideUser)
  • g_scratchpad

g_form: Object properties are the fields from the currently loaded record. Object values are the field values when the record is initially loaded. It provides useful methods to:

  • Customize forms
  • Manage form fields and their data

Some commonly used methods:

  • flash(), showFieldMsg()
  • getValue() always returns a string value irrespective of field datatype
  • setValue(), clearValue()
  • addOption(), clearOption()
  • getSections(), isNewRecord()

g_user: Contains session information about the currently logged in user.

ProptertiesMethods
firstNamegetClientData()
LastNamegetFullName()
userIdhasRole()
usernamehasRoleExactly()
hasRoleFromList()
hasRoles()

Do not rely on g_user methods to apply security.

g_scratchpad: Object passed to client-script from server-side script known as a Display Business Rule.

g_scratchpad is not available on mobile

Client-side Debugging

Script Debug Messages: Include addInfoMessage(), addErrorMessage() and showFieldMsg() methods in your script. All users are affected when these methods are used as everyone sees the output on the form.
Response Time Indicator: Useful for locating the cause of slow page loads. Enable glide.ui.response_time to true.
Try / Catch: Default javascript debugging, only catches runtime errors.

Reference Objects just store the sys_id of a record instead of a record. So when we want record of sys_id we have to get that from server.

UI Policies

UI Policy: Defines the behavior and visibility of fields on a form. Condition must be true for it to execute, if there is no condition they execute every time a form loads and / or is changed.. Always executes after Client Scripts. There are more than 2100 UI policies in baseline implementation. If you can always use a UI policy instead of client script for faster load times and easier maintenance.

System UI > UI Policies

 Catalog Policy

Policy Scripting: Ability to script complex condition and execute advance behavior

  • Show / Hide sections (tabs)
  • Remove / add / change / validate data in fields

Business Rules

Overview

Business rule: JavaScript that runs when a record is displayed, inserted, updated, deleted or queried. Can be used to change values in fields when certain conditions are met. It doesn’t monitor forms or lists and executes on server-side. More than 2000 business rules exist in the baseline implementation.

System Definition > Business Rules

When Business Rules Run
Before Query: Execute before a query is sent to the database. They execute synchronously, the current business rule must finish execution before the next business rule runs.
Display: Execute after the data is read from the data base and before the form is presented to the user. The g_scratchpad global object has no property / value pairs unless populated by a Display Business Rule.
Before: Execute after form submission and before record is updated in the database. They run synchronously.
After: Execute after form submission and record updated in the database. They run synchronously.
Async: Execute after records are inserted / modified / queried. Runs asynchronously as Scheduled Jobs. Async Business Rules are queued by the scheduler to run as soon as they can be fit in, this allows the current transaction to finish without waiting for the rule.
> System Scheduler > Scheduled Jobs > Scheduled Jobs
What Business Rules Execute
Trigger-Actions:
- Set field values
- Add message
- Abort action
Trigger-Advanced:
- Script

Global Variables:

  • current
  • previous this object is not availabe in Async Business Rules
  • g_scratchpad

Debugging

Glide System Logging Methods:

  • gs.info()
  • gs.error()
  • gs.warn()
  • gs.debug()
  • gs.log() (global)

System Logs > System Log

Script Debugger: Used for debugging server-side javascript, requires the script_debugger or the admin role. The Script Debugger only debugs server-side synchronous scripts. It is not possible to step through scripts running asynchronoulsy as they are not running the same session as the logged-in user.
The administrator can reset all Script Debugger instances by navigating to the debugger_reset.do page.

System Diagnostics > Script Debugger
Studio > File > Script Debugger

Script Tracer: User for debugging server-side javascript. It helps you filter your debugging search to quickly narrow down script problems.

System Diagnostics > Script Tracer

GlideSystem

API: Executes server-side and provides access to system level information:

  • Logged in user
  • System
  • Date and time

User Methods: Returns information about the currently logged in user.

  • getUser()
  • getUserDisplayName()
  • getUserID()
  • getUserName()
  • hasRole()
  • hasRoleInGroup()

System Methods: They primarily work with form objects, tables, fields and logging.

  • getProperty(): returns the value of a Glide property
  • getPreference(): gets a user preference
  • getDisplayColumn(): gets the display column for the table
  • tableExists(): returns boolean value
  • nil(): returns true if a field value is null or an empty string("")
  • eventQueue(): queues an event for the Event Manager
  • print(): writes a message to the system log
  • log(): logs a message to the system log and saves it to the syslog table
  • logError()
  • getMessage(): retrieves a message from UI messages

Date and Time Methods: Used to work with date and time data

  • beginningOfLastWeek()
  • beginningOfNextMonth()
  • dateDiff()
  • endOfLastWeek()
  • endOfNextMonth()
  • minutesAgo() / daysAgo() / quartersAgo() / monthsAgo() / yearsAgo()
  • now()
  • nowDateTime() GlideDate and GlideDateTime Objects

Scoped GlideSystem: You must use scoped APIs when developing scripts for scoped applications. You can’t call a global Glide API in a scoped application. The Scoped GlideSystem API does not provide methods to work with date/time fields. Use GlideDate or GlideDateTime

GlideRecord

Overview

GlideRecord: Used for database operations instead of writing SQL queries and executes on the server-side. GlideRecord queries can be called client-side, but this should be avoided due to performance impact.

Creating a new GlideRecord:

  1. Create a GlideRecord Object for the Table of interest
var myObj = new GlideRecord('incident');
  1. Build the Query Conditions
myObj.addQuery('state', '>', 5);
myObj.addQuery('priority', '=', 3);
myObj.addQuery('work_notes', 'CONTAINS', 'Fixed');
 
// Some operators
// STARTSWITH
// ENDSWITH
// DOESNOTCONTAIN
  1. Execute the Query
myObj.query();
// If a table the 'query' column use _query() method.
  1. Process Returned Records With Script Logic
while(myObj.next()) {
	// Script Logic
	// Reference current record as <object-name>.<property>
}
 
if (myObj.hasNext()) {
	// Script Logic
}

Update:

while (inc.next()) {
	inc.work_notes = 'Updating';
	inc.update();
}

addOrCondition():

var myObj = new GlideRecord('incident');
var q1 = myObj.addQuery('category', '=', 'Hardware');
q1.addOrCondition('priority', '!=', 1);

get(): Use to query for a single record

if (!current.parent_incideent.nil()) {
	var myObj = new GlideRecord('incident');
	myObj.get(current.parent_incident);
	myObj.u_rca = true;
	myObj.update()
}

Confirm Records Returned:

// Using getRowCount(), this method is very costly
var myObj = new GlideRecord('incident');
myObj.addQuery('caller_id', '=', current.caller_id);
myObj.query();
var getRows = myObj.getRowCount();
 
// Using GlideAggregate
var count = new GlideAggregate('incident');
count.addQuery('caller_id', '=', current.caller_id);
count.addAggregate('COUNT');
count.query();
var incidents = 0;
if (count.next()) {
	incidents = count.getAggregate('COUNT');
}

addEncodedQuery(): copy filter query from conditional builder.

myObj.addEncodedQuery('state=7')

GlideRecordSecure: Class inherited from GlideRecord. Performs the same functions as GlideRecord AND enforces ACLs.

GlideQuery

GlideQuery: It’s an alternative to GlideRecord but easy. It’s written in 100% javascript. It uses SQL like syntax and provides a good looking error format.

// Insert
new GlideQuery('sys_user')
	.insert({
		user_name: 'john.doe',
		first_name: 'John',
		last_name: 'Doe',
		roles: 'itil'
	})
	.get(); // optional
 
// Retrieve
new GlideQuery('sys_user')
	.where('user_name', 'john.doe')
	.select('sys_id', 'roles')
	.forEach(function(u) {
		gs.info('sys_id = ' + u.sys_id);
	});
 
// Update
new GlideQuery('sys_user')
	.where('first_name', 'john')
	.update({
		roles: 'admin'
	});
 
// Delete
new GlideQuery('sys_user')
	.where('active', true)
	.where('user_name', 'john.doe')
	.deleteMultiple()

Script Includes

Overview

Script Include: Stores reusable JavaScript for execution on the server, must be called to run. can also be client-callable. They load only on demand and do not impact performance. More than 1100 Script includes exist in baseline.

System Definition > Script Includes

Types:

  1. Store One Classless Function
  2. Define a New Class
  3. Extend an Existing Class

Reference Qualifiers: A fancy term for filters

  • Simple
  • Dynamic
  • Advanced

Classless / On Demand: This script include stores only a single function, not callable from client-side. Script include name MUST be identical to the function name.

New Class: Stores multiple functions. Script class name and Script Include name should be SAME. Functions in the class are separated by commas.

Extend an Existing Class: Create a new class to store new functions, reference an existing class using the extendsObject() method. Some commonly extended classes:

  • AbstractAjaxProcessor: Used to call script include from client-side
  • LDAPUtils
  • Catalog
var NewClass = Class.create();
NewClass.prototype = Object.extendsObject(OldClass, {
	type: 'NewClass'
});

GlideAjax

GlideAjax: Enables Client Scripts and UI Policies to call server-side code in Script Includes. Steps include:

  1. Create a new GlideAjax object for the script include of interest
  2. Pass parameters to the script include
  3. Make an asynchronous call to the server
  4. Callback function processes returned data
var gd = new GlideAjax('HelloWorld');
// sysparm_name is reserved for the method name
gd.addParam('sysparm_name', 'alertGreeting');
gd.addParam('sysparm_user_name', 'John');
gd.getXML(HelloWorldParse);
 
function HelloWorldParse(response) {
	var answerFromXML = response.responseXML.documentElement.getAttribute("answer");
	alert(answerFromXML)
}

JSON (JavaScript Object Notation)

JSON: It’s a data exchange format, low overhead alternative to XML. Serializes and passes data between server and client. Return JSON format by using JSON.stringify(object), when you return this JSON object is contained in an XML wrapper.

var gd = new GlideAjax('HelloWorld');
gd.addParam('sysparm_name', 'alertGreeting');
gd.addParam('sysparm_user_name', 'John');
gd.getXML(HelloWorldParse);
 
function HelloWorldParse(response) {
	var myObj = JSON.parse(response);
	for (var i = 0; i < myObj.length; i++) {
		g_from.addinfoMessage(myObj[i]);
	}
}

Application Scope

It’s important in Script Include. A scope prefix is not required to call a Script Include in the same scope. to call script include in another scope, prepend the script includes name with its unique scope namespace to distinguish it from other scipt includes with the same name.

var tmp = new x_app_scope.script_include_name();

Protection Policy: Only applies when applications are installed from the ServiceNow App Store.

  • None
  • Read-only
  • Protected

Flow Designer Scripting

Overview

Inline-Script: They offer the ability to modify input values, such as small format conversions, data transformations or math operations.

More Actions > Flow preferences > Show inline script toggle

Error Handler: Used to catch error and runs a sequence of actions and subflows to identify and correct issues. You can add up to 10 items in the Error Handler section, including actions, flow logic and subflows.

FlowAPI vs FlowScriptAPI

FlowAPI: Use this to execute actions, flows or subflows in server-side scripts using either blocking or non-blocking methods.
FlowScriptAPI: This allows us to access Flow Designer context details from script steps and inline scripts. Objects of this type are created automatically and are accessible only in script steps and inline scripts.

API Call Order:

  1. Create a builder object.
  2. Specify Flow Designer content to run.
  3. Retrieve Flow Designer execution details.

GlideFlow: Used for client side interactions with Flows, Subflows and Actions.

GlideFlow.startFlow(String<scoped_name>, ObjectInputs)
GlideFlow.startSubflow(String<scoped_name>, ObjectInputs)
GlideFlow.startAction(String<scoped_name>, ObjectInputs)

client_callable_flow_object ACL needs to be assigned to the Flow for it to be client-callable

Custom Actions: Use this when there is a need for functionality that the ServiceNow provided actions do not provide. The action_designer role is required to build custom Actions.

image

To view Action executions:
More Action > Executions


If you find any mistakes or want to add any more information to this blog, submit a pull request at Scripting.md