Example 2: Retrieving specific records from a third-party source
Summarize
Summary of Example 2: Retrieving specific records from a third-party source
This example demonstrates how to create a ServiceNow script that retrieves specific incident records from a third-party source using the Remote Table API. It leverages RESTMessageV2 to call external REST services and applies the Transformer API to parse and map the external JSON response into ServiceNow remote tables.
Show less
Key Features
- Conditional Query Handling: The script distinguishes between three query scenarios:
- Retrieve a specific incident by
sysidwhenvquery.isGet()is true. - Retrieve incidents filtered by
calleridwhen the parameter is provided. - Retrieve all incidents when no specific filters apply.
- Retrieve a specific incident by
- RESTMessage Integration: Uses the
snws.RESTMessageV2API with predefined REST message names and functions (e.g., 'Remote Instance Incidents' with 'All Incidents', 'By SysId', and 'By CallerId') to call external incident data sources. - Error Handling: Checks for errors in REST responses and sets appropriate error messages on the query object (
vquery.setLastErrorMessage()) to inform users when data retrieval issues occur. - Data Transformation and Mapping: Utilizes ServiceNow’s Transformer API to define a mapping schema between the JSON response fields and the remote table columns. The
getTransformerDefinition()function specifies JSON paths to map fields likeactive,callerid,number,shortdescription,sysid, andupdates. - Dynamic Row Addition: Parses the transformed JSON data and adds each mapped record as a row into the remote table (
vtable.addRow(row)), enabling real-time data integration into ServiceNow.
Practical Benefits for ServiceNow Customers
- Enables seamless integration of external incident data into ServiceNow, allowing you to query and display third-party records as if they were native table entries.
- Supports granular data retrieval by specific record ID or caller, improving efficiency by fetching only the necessary data.
- Provides robust error reporting to quickly identify issues during data fetch operations.
- Offers a customizable transformation layer to adapt external data schemas to your ServiceNow table structure.
- Facilitates extensibility by allowing additional query parameters and transformation rules to be added as needed.
In this example, we create a script to retrieve specific types of incident records from a third-party source.
/**
* Using `v_query`, add the rows to `v_table`
*/
(function executeQuery(v_table, v_query) {
if (v_query.isGet()) {
bySysId(v_table, v_query, v_query.getSysId());
}
else if (v_query.getParameter("caller_id")) {
byCallerId(v_table, v_query, v_query.getParameter("caller_id"));
}
else {
fetchAllIncidents(v_table, v_query);
}
/**
* fetch all incidents records from the remote instance
*/
function fetchAllIncidents(v_table, v_query) {
// Uses RestMessage with name 'Remote Instance Incidents' and function 'All Incidents'
// Create a RestMessage first which calls an external REST service
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'All Incidents');
loadData(v_table, v_query, restMessage);
}
/**
* fetches a specific record from the remote instance with Sys Id being `sys_id`
*/
function bySysId(v_table, v_query, sys_id) {
// Uses RestMessage with name 'Remote Instance Incidents' and function 'By SysId'
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'By SysId');
// sets variable 'sys_id'
restMessage.setStringParameterNoEscape("sys_id", sys_id);
loadData(v_table, v_query, restMessage);
}
/**
* fetches records from the remote instance with Caller (caller_id) being `caller_id`
*/
function byCallerId(v_table, v_query, caller_id) {
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'By CallerId');
restMessage.setStringParameterNoEscape("caller_id", caller_id);
loadData(v_table, v_query, restMessage);
}
/**
* Adds rows to `v_table` using `restMessage`
*/
function loadData(v_table, v_query, restMessage) {
try {
var response = restMessage.execute();
var responseBody = response.getBody();
// if REST call ends up in an error, set the last error message which shows up
// at the bottom of the list view
if (response.haveError()) {
v_query.setLastErrorMessage(response.getErrorMessage());
// can use gs.error() or gs.addErrorMessage() while debugging
// gs.debug() messages visible in session debugger
// gs.debug(response.getErrorMessage());
return;
}
} catch (ex) {
v_query.setLastErrorMessage(ex.message);
// gs.debug(ex.message);
return;
}
var transformerDefinition = getTransformerDefinition();
var transformer = new sn_tfrm.Transformer(transformerDefinition, responseBody);
// transformer parses the responseBody and extracts rows
while (transformer.transform()) {
// row is field-value map e.g. { active:"true", number: "INC0000001"}
var row = transformer.getRow();
// you may do any additional transformations to the row like GlideDuration, GlideDataTime etc. For example,
// row.duration = new GlideDuration(row.duration);
// finally add the row to the remote table
v_table.addRow(row);
}
}
/**
* returns a sn_tfrm.TransformerDefinition, which defines the mapping of the table fields and elements in the response body
*/
function getTransformerDefinition() {
// create a rule list to map a field to its element path
var ruleList = new sn_tfrm.TransformerRuleList()
.fromJSON() // the response body is a JSON
// 'active' field maps to path '$.active'
.addRule("active", "$.active")
.addRule("caller_id", "$.caller_id.value")
.addRule("number", "$.number")
.addRule("short_description", "$.short_description")
.addRule("sys_id", "$.sys_id")
.addRule("updates", "$.sys_mod_count");
var recordPath = "$.result";
return new sn_tfrm.TransformerDefinition(ruleList, recordPath);
}
})(v_table, v_query);
These code snippets are of note in this script:
function fetchAllIncidents(v_table, v_query) {
// Uses RestMessage with name 'Remote Instance Incidents' and function 'All Incidents'
// Create a RestMessage first which calls an external REST service
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'All Incidents');
loadData(v_table, v_query, restMessage);
}
You can create a RestMessage and directly use it in the script. In this example, it
uses a RESTMessageV2 API with the name of Remote Instance
Incidents, and the function All Incidents, which gets all
incident data. Once a response is returned from the server, an error message appears
if problems are encountered in the data retrieval.
function bySysId(v_table, v_query, sys_id) {
// Uses RestMessage with name 'Remote Instance Incidents' and function 'By SysId'
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'By SysId');
// sets variable 'sys_id'
restMessage.setStringParameterNoEscape("sys_id", sys_id);
loadData(v_table, v_query, restMessage);
}
When you query a specific record using
GlideRecord.get(“<sys_id>“), then
v_query.isGet()` is `true`. It fetches the
specific record from the external service.
function byCallerId(v_table, v_query, caller_id) {
var restMessage = new sn_ws.RESTMessageV2('Remote Instance Incidents', 'By CallerId');
restMessage.setStringParameterNoEscape("caller_id", caller_id);
loadData(v_table, v_query, restMessage);
}
You can also handle any other specific query conditions in the script, such as using
caller_id in the preceding code snippet. The remainder of this
script operates in a manner similar to Example 1.
function getTransformerDefinition() {
// create a rule list to map a field to its element path
var ruleList = new sn_tfrm.TransformerRuleList()
.fromJSON() // the response body is a JSON
// 'active' field maps to path '$.active'
.addRule("active", "$.active")
.addRule("caller_id", "$.caller_id.value")
.addRule("number", "$.number")
.addRule("short_description", "$.short_description")
.addRule("sys_id", "$.sys_id")
.addRule("updates", "$.sys_mod_count");
var recordPath = "$.result";
return new sn_tfrm.TransformerDefinition(ruleList, recordPath);
}
})(v_table, v_query);If no problems are encountered in the data retrieval, it gets the data body for the records. It then uses the Transformer API to perform any required data transformations, extracts rows, and then adds a row for each record to the remote table.
getTransformerDefinition defines the schema of the record in the
external API response body. It maps each of the fields in the table script to an
element in the external record. Any external data elements outside of this mapping
are not available in the remote table.