Ganesh Pardhe
Kilo Guru

Hello All, 

PFB article to do scripting in ServiceNow.

 

Introduction to Scripting

In this chapter, we're going to get a basic introduction to scripting in ServiceNow. As with the rest of we assume a basic understanding of the JavaScript scripting language, and basic familiarity with database, programming, and ITIL terminology.

ServiceNow comes in two flavors (otherwise known as editions): Enterprise, and Express. This article is largely focused on ServiceNow enterprise, as that is the more popular and more complex of the two, but most of what you've learned so far about enterprise will translate nicely to the express edition of ServiceNow as well.

That said, it's important to note that in this, and many of the following chapters, we are going to begin focusing on scripting. Scripting is almost completely unsupported in ServiceNow express, so if you're an express user, these next few chapters might not be relevant to your instance.

In this chapter, we're going to learn about:

  • When it is appropriate or necessary to employ custom or semi-custom functionality via scripting, versus using out of the box functionality
  • What sorts of fields and areas of the platform support scripting, and how to script within them?
  • ServiceNow Integrated Development Environment (IDE) versus. And external IDE
  • The purposes, and scopes of the different scriptable fields
  • How to test client side and server side scripts
  • Script execution order
  • Best practices related to scripting in ServiceNow

 

To script, or not to script?

Once you learn how powerful scripting can be in ServiceNow, it would be easy to try and do everything with custom scripts. However, this is quite often not the best solution for a few reasons:

  • If the functionality or API are updated or deprecated, any unnecessary custom code means more maintenance costs during upgrades
  • Increased custom code increases complexity, increasing the cost of development overall
  • Custom code being used in lieu of out-of-box functionality can make it more difficult to identify the source of a given behavior, making troubleshooting cumbersome

In the Where scripting is supported section of this chapter, we'll learn about the various fields and records in which scripting is supported. However, it is important to keep in mind that custom scripts do carry a small cost to offset their benefit, in terms of performance, upgradeability, and future stability.

With that said, the benefits of a custom script are very often far greater than the costs; primarily, when there is no specific functionality built into the system to accomplish what you want, without scripting. Let's look at some examples.

First, let's have a look at just a few examples where scripting is not necessary:

  • Making a field dynamically read-only, mandatory, or hidden, based on the value of another field or fields in the client
  • Altering the value of a field on submission
  • Preventing/rejecting an update under certain conditions upon submission
  • Providing an informational or error message to the user upon submission

That covers a significant percentage of the sorts of things you might need to do on a daily basis within ServiceNow, but to perform some more advanced functions, you may need to write a custom script (or indeed, leverage a script that's provided for you out of the box!) Let's look at some examples of some more advanced functionality that might require scripting:

  • Setting one field based on the value of another field in the client
  • Creating a new record programmatically based on a client or server-side action or event
  • Setting a field value on a record that cannot be directly dot-walked to from the record that triggered the event
  • Validate the contents of a field (such as ensuring that a date field is before or after a particular date) on the client

As you can see, scripting, despite not being the best way to perform certain actions, does have a myriad of uses within the platform. As a general rule, if it can be done without scripting, then it should be done without scripting.

 

Client side versus server side APIs

Originally, ServiceNow's name was GlideSoft. While that was a long time ago, there are still some indicators of the company's history, such as in the naming of ServiceNow's scripting API suite: the glide API. Scripting is an important part of ServiceNow, and many different sorts of records support scripting in one or more fields.

Some scripts execute server side, and some execute client side. Whether a script executes on the client or on the server, determines the API that it has access to. Server scripts, executing on the server as they do, have access to a different set of programming interfaces than Client Scripts, because Client Scripts execute within the browser scope. Thus, only scripts which are included in the webpage and sent from the server to the browser can be executed or called from within Client Scripts. Since it would be impractical and have a negative impact on performance to send over the entire scripting library from the server to the client for inclusion in each page, only a modified subset of the API is included.

Additionally, it's important to be aware that the server is running Mozilla Rhino; an open-source implementation of JavaScript, written entirely in Java. Rhino is embedded into the ServiceNow servers, in order to provide the JavaScript API on the server. As such, this grants special access to certain Java-specific functionality (and Java-specific headaches!) for server side scripts, that client side scripts don't have.

Similarly, scripts which execute client side have access to a specific scope of their own. Since they're executing within the user's browser, they likely have access to JavaScript ES6 syntax, whereas ServiceNow's implementation of Mozilla Rhino only supports up to ES5 on server side scripts (or ES3 if you're running Geneva or earlier).

While a complete description of the entire ServiceNow API is outside the scope of this article (you can find this information at http://developer.servicenow.com/), there are some significant differences in the APIs for client, and server-based scripts. You cannot, for example, use the g_form API from within a server side script. Similarly, you cannot use the gs (GlideSystem) API from a client side script.

As you can see earlier, there are some short-hand references to APIs such as GlideForm. The g_form object is a reference to GlideForm, so you can consider the two to be interchangeable. Similarly g_list is a reference to GlideList2 or GlideListV3 depending on the List version that's loaded in the page. gs is a reference to GlideSystem, and g_user is a reference to GlideUser. These APIs use interface references beginning with g_, because they have no constructor methods that would be invoked by using the new keyword.

While we're going to go into much more depth on the glide API in a later chapter, let's start by learning the APIs and objects that are available on the client and the server respectively. You'll notice that some objects exist on both the client and the server, but behave differently on one versus the other.

 

Client side APIs

Client side APIs are available within the browser, and load with the ServiceNow page. Let's go over some of the client side APIs that are available:

  • g_form (a reference to the GlideForm object) allows you to access, set, and get values from form elements and fields. This object has methods to add field messages, set whether fields are mandatory, visible, or read-only, and so on.
  • g_user (a reference to the GlideUser object) has methods that allow you to check if the current user (the logged-in user who's loaded the page on which the script is running) has a given role, and contains properties that give you access to the user's name and ID.
  • g_list (a reference to the GlideList2 or GlideListV3 object, depending on what list version is loaded) has methods to get, set, or change the list filter, group the list by a specified column, set the number of records to display per page. The g_list API is available from UI context menus, and client side list UI actions.
  • g_menu (a reference to the GlideMenu object) is used in UI context menus, in the onShow script. It has methods to control the menu items that do or don't show up in a UI context menu in ServiceNow.
  • GlideRecord is probably the most-used method in the glide API, because it is the means by which records in the database are generally accessed, read, and modified.
  • The client-side version of GlideRecord has vital performance implications. You can read more on these implications, and how to avoid negatively impacting client performance in the Scripting best practices section of this chapter.
  • GlideAjax is one of the most important client side APIs, as it allows you to execute server side code (specifically, client-callable Script Includes), and receive a response back to the client. It does this asynchronously, meaning that unlike synchronous queries and scripts that execute or retrieve data from the server, it does not lock up or slow down the user's browser while it executes.
  • GlideAjax is the most performance-efficient way to execute server side queries and code from within client side scripts. More on this in the Scripting best practices section of this chapter, and in a later chapter on the glide API.

 

Server side APIs

Just like on the client, scripts that execute on the server a particular set of APIs that they have access to. This API suite is broader than the client side API in part because making an API available on the client requires sending code from the server to the client, for possible execution, which can slow page loads, and also in part because server scripts execute on the server! The server has an extremely low-latency connection to the database, which makes more robust scripting possible and much more efficient.

There are two sets of APIs: scoped, and legacy. Scoped APIs are a subset of the legacy API. They are the only APIs available within scoped applications, and do have some limitations. These limitations however, are becoming fewer and fewer with every new version of ServiceNow.

Let's go over some of the APIs and objects available on the server:

  • GlideAggregate: This is an extension of the GlideRecord class, used for creating database aggregation queries such as SUM, COUNT, MIN, and MAX. For example, you can run a query with a given filter (say, all items associated with a given ticket) and get a SUM of the cost of these items in order to determine the total cost of the parent ticket.
  • GlideDateTime: This is a class meant to help with the usage of glide_date_time fields, as well as comparing one date and time to another date and time, or formatting a date/time from a string into a date/time object that can be used for time zone conversion and date/time calculations.
  • GlideDateTime: This is very similar to the GlideDate class, which is just for dates without times associated
  • GlideRecord: This is probably the most ubiquitous class in ServiceNow, and it is both a server side and client side API. It is vastly different in behavior and capability on the client, but on the server it is a powerful and efficient means of querying the database for a given record or set of records. As you can imagine, getting and setting data in the database is something you might need to do quite often in a platform like ServiceNow.
  • GlideElement: This is a class referencing a specific field on a client side GlideRecord object. To put it another way, each GlideRecord object contains one property (a GlideElement object) for each field on that record. This API provides methods for interacting with these fields and their values.
  • gs: This is a reference to GlideSystem (which has no constructor method). It provides methods with all sorts of useful system functionality, including getting system properties, logging information to the system logs, and checking user permissions.

Objects that are meant to be instantiated have a constructor method. This method must be called using the new keyword. When I write var gr = new GlideRecord('table_name');, the new keyword calls the constructor method of the GlideRecord class. This constructor is usually a function in the class called initialize, which takes the argument table_name that we specified in our call. The constructor then modifies properties of the object and returns the resulting constructed object to our variable, gr.

  • GlideSession: This is a server side object that corresponds to the currently signed-in user's session. It provides methods to get the roles associated with a user, as well as set and retrieve data associated with their particular session. You can get an instance of the GlideSession object for the current user's session by using the getSession() method of the GlideSystem API like so: var session = gs.getSession();.

Server side scripts that operate on a specific record (such as Business Rules or advanced conditions fields), also often have access to a pre-defined variable called current. This is an instance of the GlideRecord object which contains the data relating to the record upon which the script is executing.For example, say you have a Business Rules that executes on the incident table, and is triggered whenever the State field changes value. If you then go to the incident table, open up a record, and change the State field value, then the Business Rule will execute. when it does, in the context of the script that that Business Rule runs, the current object will correspond to the record that you just modified.

 

 

Where scripting is supported

Some records are defined as scripts, such that running a script is their primary function. Other records, such as business rules, will support scripting if you enable the Advanced view, but which have more basic functionality even without scripting. What might be less intuitive, is that certain fields such as the condition builder, can also support scripting if the script is invoked using the javascript: keyword.

Later, we'll go over most of the scenarios in which scripting is supported in one fashion or another, and we'll learn what

these scripts do, as well as the context in which they execute (whether on the client, or the server).

Access controls-executes on: server

In a previous chapter, we learned about how access controls (AKA security rules/ACLs) control whether a user can access a record, or perform a certain operation upon it (read, write, delete, and so on). Access controls have a great deal of functionality without scripting, but do have the capability to execute server side scripts if the Advanced tick-box is checked:

find_real_file.png

This script should evaluate to either true or false, depending on whether the ACL should allow or deny access.

Don't forget that for a user to pass an ACL challenge, all three conditions (the condition builder, roles list, and script) must all be satisfied!

Business rules-executes on: server

Much like ACLs, Business Rules actually have a significant amount of functionality without the need for scripting. Also like ACLs, Business Rules support scripting when the Advanced tick-box is checked, in the Script field which will then be displayed.

Business Rules execute on the server, so the usual server side APIs are available to any scripts that might need to be run. Much like many other server side scripts, the current object is also available. This object is a pre-populated GlideRecord containing the current record; that is, the record which triggered this Business Rules to run by being changed.

Based on the value selected in the When field, under the When to run section of the Business Rules form, a Business Rules can execute either before the record has been saved to the database, after the record has been saved, asynchronously (some time after the record has been saved to the database, when the server gets around to it), or on display (when the record is requested from the database to be shown on a form):

find_real_file.png

 

 

Client scripts and catalog client scripts-executes on: client

Client Scripts and catalog Client Scripts are virtually the exact same sort of script. The differences are that client scripts execute against a form with a certain type of record, whereas catalog Client Scripts execute against a certain catalog item or variable set within a catalog item.

In either case, both script types execute exclusively on the client (meaning inside the user's browser). As such, they unfortunately do not have access to some very useful server side APIs, but there are ways around that. We'll get into how to execute server side code and APIs from a client side script in a later chapter.

Client Scripts can be used to show and hide options from within a drop-down list, add messages to fields, show alerts to the user, or even replace the functionality of UI policy actions (though that is not recommended).

Depending on the value of the Type field, Client Scripts can run either onLoad (as soon as the form loads), onChange (whenever a specified field's value changes), onCellEdit (when a cell on a list changes value), or onSubmit (when the user attempts to submit the form):

find_real_file.png

Condition builder (and the URL)-executes on: server

Perhaps a lesser-known area that supports scripting, is the condition builder in ServiceNow. You can use simple scripts to grab and return values to be used within a query, by using the keyword javascript: at the beginning of your query parameter:

find_real_file.png

For example, if you navigate to the Incident list, and create a new filter that says Caller, is, javascript:gs.getUserID();, and click Run, then you'll be presented with a list of all incidents for which your user account (or the user account you're impersonating) is the Caller. If you then right-click the query breadcrumb and click Copy URL as you can see in the following screenshot, the URL will contain the JavaScript code you used to retrieve your tickets as part of the encoded query (the part of the URL following sysparm_query=). If you give this link to another user, they'll see the tickets for which they are the caller, rather than you:

find_real_file.png

 

Default value-executes on: server

Like many fields within ServiceNow, the default value field accepts JavaScript by prefacing it with the javascript: keyword, just like in the condition builder. Scripts within this field even have access to the current object, and you can dot-walk through Reference fields in them.

For example, let's say you want the country field in a given table to be set to the same value as the country field on the Caller's user account. To accomplish this, you could navigate to the country field's dictionary entry, and set its default value to: javascript:current.caller_id.country.

Script Includes-executes on: server

A Script Include is a repository for reusable code. It is always available on the server, and doesn't need to be included in a page or loaded with a form. Any code that executes server side and in the same scope as the Script Include, can call it like any other API in the system.

Script Includes are not triggered by a database action like Business Rules, or by an event like Client Scripts. Instead, Script Includes are scripts which exist on the server, and are called from other server side scripts. You cannot directly call a Script Include from a client side script, but you can make a Script Include accessible from a client side script (though it still executes on the server) by making it extend the GlideAjax class. More on that in a future chapter. For now, suffice it to say that Script Includes only execute on the server, and only when called from another server side script.

UI actions-executes on: client and/or server

UI Actions correspond to buttons in the banner, links under Related Links in the form, options in the context menu, and a few other places:

find_real_file.png

UI actions can be configured to run either server side, or client side. It is also possible to configure a UI Action to run some code on the client, and other code on the server.

As with most condition fields, the conditions for whether to display the UI Action are evaluated on the server.

UI policies and catalog UI policies-executes on: client

UI policies and catalog UI policies define the behavior and visibility of fields on forms and catalog items. UI Policies operate on a specific table, while catalog UI policies operate on a specific catalog item or variable set.

UI policies and catalog UI policies operate entirely client side.

UI scripts-runs on: client

UI scripts are quite a lot like Script Includes. While Script Includes are libraries of code that are available to any script running server side, UI scripts are libraries of code which are available to any script which runs client side, on a page where the UI script is included (or if the UI script has the Global tick-box checked, then code within it can be called from any form, list, or page on the client.

UI scripts are a great way to avoid re-writing the same code over and over, and maintain a central repository for a given set of methods or APIs. This can save you time, and help with maintainability.

Of course, having code available on the client means that it must be sent from the server to the client, and be loaded in the user's browser. This can have performance implications during page-loads, and whenever these scripts are invoked. For this reason, it is wise to be judicious about using the Global tick-box on UI scripts. Instead, it would be wise to specifically load these scripts on pages and tables where you know they'll be used, and avoid loading them when they're not called or don't serve a purpose.

Workflow activities-executes on: server

Workflow activities always execute on the server by nature and design. These scriptable activities obviously consist of the run script workflow activity, but also include activities like the create task activity, or the If conditional activity. These scripts have access to the current object, and are evaluated at the time the activity is invoked via the workflow process. If an activity is not invoked through the natural progression of the workflow, then the script(s) it contains will also not be run.

In addition to any Script fields, all conditions are also evaluated on the server, which means that they are not re-evaluated, and the workflow will not progress, until a record is saved to the database.

Integrated development environment

In previous versions of ServiceNow, Script fields consisted of little more than string text fields with some syntax highlighting. However, in Geneva and later (including Helsinki, and soon, Istanbul) the Script fields have become more IDE-like. These fields which are designed to accept scripts now support more advanced syntax highlighting, error checking (otherwise known as Linting), and even some degree of intellisense-style code auto-completion for known APIs:

find_real_file.png

For server side scripts with access to the current object for example, the new Script field IDE will even auto-complete and predict field names (though this only works on table-specific records after the record has been saved):

find_real_file.png

If it is not already acon your instance, you can enable this functionality by activating the syntax editor plugin (com.glide.syntax_editor).

In the event of an error, the syntax editor will parse your code and attempt to detect the error for you, highlighting the appropriate line. If you attempt to submit the form, saving the code with the syntax error, a warning will be shown after the field and the update will be rejected:

 find_real_file.png

Script tree

Certain script records, such as Business Rules, have an easy way to view the glide script API tree, which gives you an expandable tree-view of the server side glide API:

find_real_file.png

Simply clicking on the API in the list will not auto-populate the full call, but it will populate the method call. For example, expanding the System tree, and clicking on addInfoMessage, it will populate addInfoMessage(Object, String). You will have to write parent-object call (gs.).

The script tree is a great way to get a quick reference as to the exact methods available in the API you're using.

 

Script auto-completion

The script editor provides keyboard and action shortcuts that trigger assistive functionality for writing code and completing API calls. Here are a few examples.

While writing code, type a period (.) after a valid class name or reference will open the auto-complete dialog, displaying the documented callable methods of that class:

find_real_file.png

The script editor browser-based IDE can also auto-complete more than just method names. By pressing Ctrl + Spacebar while typing, the script editor will auto-complete:

  • Class names
  • Function names
  • Object names
  • Variable names

Just as with the other auto-completions, selecting an entry will display a short description of the class or function:

find_real_file.png

One more way to auto-complete your code (or at least get some help), is to type a documented class or function, and then type an open parenthesis(()). This will indicate what arguments the function or object constructor method expects, and what data type it expects it to be:

find_real_file.png

 

Script editor macros

The ServiceNow script editor/integrated IDE supports macros, which can be accessed by typing a keyword, and then pressing Tab. This feature is still relatively seldom-used, and we hope that ServiceNow will continue to expand it. Let's look at some of the script editor macros that are built-in, and then we'll make some enhancements to them and see how we can create a custom script editor macro ourselves! Before we get started though, remember that you can access the list and description of script editor macros any time, by typing help followed by the Tab key.

Documentation macro

The first Editor macro is doc. Typing doc into a Script field and pressing Tab will populate some JSDoc-type headers for a function/method, including things space for a description of the code, what it expects as parameters, and what it returns. JSDoc is an important JavaScript documentation standard which organizes and simplifies your code documentation so that IDEs can read and present it to anyone who may call your code in the future, as instruction on how to call it, and what to expect from it:

find_real_file.png

You can also automatically generate a class method for use within a Script Include, which already has the JSDoc header included. This isn't exactly standard JSDoc formatting, but it provides some basic information to anyone who's trying to read or reference your code, which is essential!

As you can see in the following screenshot, the macro also does not populate the method name (before the colon), input parameters (between the parentheses), and code. It's expected that you'll populate this information after the macro is generated:

find_real_file.png

When defining a script editor macro, there's a way to define where the user's cursor ends up after the macro text is generated. We'll learn more about that shortly, when we update the method macro to be a little more helpful!

 

 

For-loop macro

A for loop in JavaScript is generally used to iterate over each instance of something, or to go through each child member of an object or array. For example, you might want to iterate over every member variable in an array.

You can easily generate the scaffolding of a for loop by typing for and pressing Tab. This will iterate over each element in an array called myArray. Of course, assuming you don't have an array called myArray, you'll need to change this to fit the correct name of your array variable. This is common throughout script editor macros, as they only provide a static scaffolding which you'll need to adjust to fit your purpose:

find_real_file.png

 

GlideRecord macros

Two macros you might just find yourself using frequently, are vargr and vargror. Both of these macros generate a GlideRecord and query.

Vargr adds a single query condition, but of course you're able to add more. It also generates an if block that's triggered if a record is found matching your query.

Vargror on the other hand, adds a condition with an or condition attached to it (as in if this, OR that), and a while loop rather than an if block:

find_real_file.png

Neither the vargr, nor vargror macros utilize the appropriate asynchronous client side syntax, which we'll learn about in a later chapter. As a self-study exercise, you might want to create a new syntax editor macro that generates an asynchronous client side GlideRecord query.

 

Demo

There is already a macro for scaffolding out a for loop (Hint: It's for), so let's build one for a do-while loop.

If you're not familiar with a do-while loop, it's just like a while loop, except that the do comes before the while, so the code block executes at least once before the conditions are evaluated (whether they would evaluate to true or not). If the condition in the while expression evaluate to a truthly value, then the do block executes again and again, until the condition evaluates to a falsely value. A do-while loop generally looks something like this:

do {
/*code that will execute at least once*/
} while(/*condition*/);

 

To create our own editor macro, let's follow the following steps:

  1. In the Application Navigator, head over to System Definition | Syntax Editor Macros.
  2. At the top of that list, click on the blue New button to create a new syntax editor macro.
  3. In the Name field, enter the string of text that you'd like to use to trigger the macro. Since we're writing a do-while macro, let's use the string dowhile as our macro name.
  4. In the Comments field, we'll write a description of what the macro generates. Let's enter something like A typical do-while code block, with a blank condition at the end.
    1. After we save this record, triggering the help syntax editor macro by typing help and then pressing Tab will include this help text next to the macro name.
  5. In the Text field, enter the following code. The $0 indicates where the user's cursor should land after the macro is triggered:

do {
$0
} while(/*condition*/);

find_real_file.png

Right-click on the header, and click Save to submit the record to the database. From now on, you'll be able to type dowhile into any Script field, press Tab, and this macro will appear in the script editor!

 

If you get any help from this article, Please mark helpful. 

 

Regards,

Ganesh

 

Version history
Last update:
‎10-14-2020 11:58 PM
Updated by: