ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

54
Advanced Scripting & Debugging Lab John Roberts Application Developer ServiceNow Jerrod Bennett Senior Technical Consultant ServiceNow

description

In this advanced hands-on workshop you will work with a variety of debugging tools to troubleshoot client and server scripting. You'll learn how to add error handling and debugging assistance to your scripts. We will review some advanced scripting techniques including server-side script includes extending base classes and AJAX client requests. As we will not be covering basic scripting concepts in this session participants will require some understanding of JavaScript and scripting within ServiceNow.

Transcript of ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Page 1: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Advanced Scripting & Debugging Lab

John Roberts Application Developer ServiceNow

Jerrod Bennett Senior Technical Consultant ServiceNow

Page 2: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

•  Overview

•  Scripting & Debugging Concepts

•  Debugging Tools

•  Client and Server Debugging Examples

•  Extending Script Includes

•  AJAX Debugging

•  Basic Jelly Debugging

•  Display Business Rules

Lab Agenda

Page 3: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Overview

•  Disclaimer •  Advanced topics and quick pace

•  Assumes some scripting experience and knowledge of Service-now.com concepts

•  Objectives •  Improve scripting and troubleshooting abilities

•  Learn some new tricks

Page 4: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Overview

•  Setup •  Lab instance

•  Script source - http://wiki.service-now.com/index.php?title=Script_Lab

•  Optional •  Install Firefox and Firebug

Page 5: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Scripting Concepts (quick review)

•  Case SenSitiviTy

•  All commands, functions, variables, …

•  Variable Scope

•  Session global – risk of duplication

•  Classes – limited to class

•  Function – limited to function, best protection

var  myName  =  “john”;  func4on  doThis()  {  

 var  myName  =  “roberts”;    }  

Page 6: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Scripting Concepts (quick review)

•  Reference vs Value values

•  Reference var myId = gr.sys_id;

•  myId will change as gr changes

•  Value var myId = gr.sys_id.toString();

•  myId will only change if explicitly changed

Page 7: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Scripting Concepts (quick review)

•  Try/Catch blocks for proper error handling

•  Errors will halt script unless handled

try { //something } catch (err) { gs.log(“ERROR: “ + err); }

Page 8: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Concepts

•  Know what should happen

•  Identify what is happening

•  Did my script run, were there errors

•  Do I have the expected results

Page 9: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Tools

•  Application •  System Diagnostics / Session Debug modules

•  Information output options

•  Browser •  Developer Tools

•  Add-ons such as Firebug

Page 10: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 1

Business Rule Debug

Page 11: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  Scenario: business rule adds comments when incident state changes

to closed •  Problem: no comments are being added •  Business rule: k11 Exercise 1 – Incident Close Comment

Page 12: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  Try it

–  Open an existing incident –  Set incident state to Closed –  Using header context menu, save the record

•  Result –  No comment or info message

•  Troubleshooting –  Did the rule execute

Page 13: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  Identifying whether a business rule was executed

•  Run the Debug Business Rules module to enable business rule debugging

–  Just the Debug Business Rule, no jumping ahead to (Details) yet

•  Open another existing incident and set incident state to closed, save

•  Scroll down to see debug output and notice the following Skipping 'k11 Exercise 1 - Incident Close Comment' on table incident; condition not satisfied: current.incident_state.changesTo("Closed")

•  From the debug output click on the business rule name to open it

Page 14: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  For some reason our condition is not being satisfied

–  current.incident_state.changesTo("Closed")

•  Let’s remove the condition and find out what the field value is changing to

–  Delete the condition so the rule will execute –  Comment out the comment set statement so it doesn’t run on all incidents –  Add some debugging statements

//add comment when closing//current.comments = "Closed by " + gs.getUserName() + " at " + gs.nowDateTime();//gs.addInfoMessage("Close comment added");

// Debug infogs.addInfoMessage("(InfoMessage) Incident state = " + current.incident_state); //output to appgs.log("(Log) Incident state = " + current.incident_state); //output to system loggs.print("(debug print) Incident state = " + current.incident_state); //output to debug console

Page 15: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  Open another existing incident and set incident state to closed,

save •  Scroll down to see debug output and notice the following

3:50:23.714: ==> 'k11 Exercise 1 - Incident Close Comment' on table incident 13:50:23.718: : (Log) Incident state = 7 13:50:23.718: : (debug print) Incident state = 7 13:50:23.719: <== 'k11 Exercise 1 - Incident Close Comment' on table incident

•  Looks like we had the wrong condition value for closed incident state •  Now we can correct the condition and un-comment the business

rule

Page 16: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 1 – Debug Business Rule •  Perform one more test to verify

•  If we suspected the field value was wrong we could have taken a shortcut

–  From a closed incident form, use the header context menu Show XML to display all fields and values

Page 17: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 2

Debug Business Rule Changes

Page 18: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 2 – Business Rule Changes •  Scenario: whenever we create a hardware incident the priority is set

to 1, we suspect it might be a business rule

•  Try it –  Create a new incident and set category to Hardware –  Save the incident, and notice the priority value has changed to 1

•  Debugging –  Enable the Debug Business Rule (Details) to add detail to the debug output –  Create another hardware incident, save –  View debug output

==> 'k11 Exercise 2 - Incident Priority Change' on table incident priority: 4 => 1 <== 'k11 Exercise 2 - Incident Priority Change' on table incident

–  Looks like we found the rule changing the priority value

Page 19: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 3

Try … Catch Line by line evaluation

Page 20: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 3 – Error Handling •  Scenario: simple business rule should add message when saving a

software incident •  Problem: we are only getting one of the three messages we expect

•  Try it –  Create a incident with software category –  Add a short description and save –  Notice we are getting one message at the top of the form

Page 21: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 3 – Error Handling •  Following the javascript processor line by line •  Run the JS Debug Activate module to enable the Rhino debugger •  Create another software incident and view the debug output •  Search the page for “Exercise 3” to find the related script processing

==> 'k11 Exercise 3 - Display Info' on table incident evaluate://output current number gs.addInfoMessage("Current number: " + current.number); //output current

short_description gs.addInfoMessage("Current Short Description: " + currrent.short_description); //output current category gs.addInfoMessage("Current Category: " + current.category);

>>> line(2) gs.addInfoMessage("Current number: " + current.number); >>> line(5) gs.addInfoMessage("Current Short Description: " + currrent.short_description); <== 'k11 Exercise 3 - Display Info' on table incident

•  Notice we don’t process after line 5, now we need to find out why •  First disable the rhino debugger by running the Disable All module

–  Rhino debugger can interfere or suppress error output

Page 22: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 3 – Error Handling •  Enable both Debug Business Rule and Debug Log modules

•  Create another software incident and view the debug output

•  Notice that we have a script exception because we have an extra “r” in current

==> 'k11 Exercise 3 - Display Info' on table incident

Evaluator: org.mozilla.javascript.EcmaError: "currrent" is not defined. Caused by error in Business Rule: 'k11 Exercise 3 - Display Info' at line 5 2: gs.addInfoMessage("Current number: " + current.number); 3: 4: //output current short_description ==> 5: gs.addInfoMessage("Current Short Description: " + currrent.short_description); 6: 7: //output current category 8: gs.addInfoMessage("Current Category: " + current.category);

<== 'k11 Exercise 3 - Display Info' on table incident

•  Now let’s see how try … catch block can help us

•  From the debug output click on the business rule to open it

Page 23: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 3 – Error Handling •  Add a try catch block around our statements and save the business

rule

try { //output current number gs.addInfoMessage("Current number: " + current.number);

//output current short_description gs.addInfoMessage("Current Short Description: " + currrent.short_description);

//output current category gs.addInfoMessage("Current Category: " + current.category);}catch(err) { //catch only runs on exception in try block //err object is passed from the try handler and includes gs.log("Error in k11 Exercise 3 business rule: " + err);}

Page 24: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 3 – Error Handling •  Create one more software incident and see how the catch

statement provides information

==> 'k11 Exercise 3 - Display Info' on table incident : : Error in k11 Exercise 3 business rule: ReferenceError: "currrent" is not defined. <== 'k11 Exercise 3 - Display Info' on table incident

•  Unhandled errors can prevent script functionality and even other scripts from running

•  Catch statements guarantee that you control what happens when an error occurs, especially important if you need to clean up or revert something

Page 25: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 4

Client Script

Page 26: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 4 – Client Script •  Scenario: incident table has an on-change client script for category

function onChange(control, oldValue, newValue, isLoading, isTemplate) { if (isLoading || newValue == '') return;

if (newValue == "request") { g_form.setValue("urgency", 3); jslog("k11 Exercise 5 Request Category client script: Setting urgency to low

for requests"); }}

•  Try it –  Let’s review options for client-side debug output –  Enable client javascript debugger console by clicking the green bug in the top

banner –  Create a new incident, change category to request –  Script will log to debug console and change urgency to low –  Review debug console

Page 27: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 4 – Client Script •  Using browser debuggers (Firebug)

•  From a new incident form, open Firebug and make sure it’s active

•  Go to the script tab and search for g_form.setValue("urgency”, so we can locate our script

•  Set a break point by clicking in the gray area left of the line numbers

Page 28: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 4 – Client Script •  Change the category to request to execute the script again

•  Firebug breakpoints can be funny at times, refresh the form script does not stop at breakpoint

•  Review all the information available during the break

•  You can also step through code using the yellow arrows

Page 29: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 5

Javascript Executor

Page 30: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 5 – Javascript Executor •  Scenario: it would be nice to have a fast way to test client scripts

without actually creating them first •  Solution: Javascript executor has access to the same client

environment as client scripts

•  Try it: –  From a change request form, press <Shift><Ctrl><Alt><j> to launch the

javascript executor –  See that the description field is mandatory, let’s test a script to change that –  g_form.setMandatory("description", false); –  Click Run My Code button –  Notice the mandatory flag has been removed, let’s add it back and add a short

description –  g_form.setMandatory("description", true); –  g_form.setValue(“short_description”, “Testing”);

Page 31: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 5 – Javascript Executor •  Now for a cool admin trick •  Close the executor and verify that you cannot save the form with a

blank description field •  Re-open the executor and run

–  g_form.checkMandatory = false; –  Run My Code

•  Close executor •  Try to save the form again with a blank description •  You just temporarily bypassed the mandatory check on the form •  Use it wisely and keep it a secret

Page 32: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 6

Background Scripts

Page 33: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 6 – Background Scripts •  Scenario: admin needs a way to test server side scripts or perform

some maintenance that requires a script

•  Solution: background scripts are the server side version of Javascript executor

•  Warning: this can really be dangerous, and even crash an entire instance if you get something wrong

Page 34: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 6 – Background Scripts •  Try it

–  Let’s build a script to disable some users –  Launch the background script module –  Enter the following script

Page 35: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 6 – Background Scripts •  Notice that we have commented out the update line •  It’s always best to see the possible results before you actually do

anything •  Run the script to see the results

•  If this is a script you need frequently you can also save it to the server

•  Upload a script file with “.js” extension using the file upload module

•  It will be available in the customer scripts for future reference and execution

•  To be safe you can leave the function call commented when you upload so you purposely have to view and change it before it does anything harmful

Page 36: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 7

Extending Script Includes

Page 37: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 7 – Extending Script Includes •  Scenario: I like the functionality provided by the TableUtils script

include but want to change it a bit

•  The getTables method in TableUtils class returns the parent list of table hierarchy, but it returns it in a java array list not an array

•  For example you can’t enumerate a java array list like you would with a Javascript array

//enumerate java array listfor (var i=0; i < tables.size(); i++) {gs.print(tables.get(i));}

//enumerate javascript arrayfor (var i=0; i < tableArray.length; i++) {gs.print(tableArray[i]);}

Page 38: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 7 – Extending Script Includes •  Try it

–  From background scripts get the tables hierarchy for cmdb_ci_win_server

var util = new TableUtils("cmdb_ci_server");//getTables returns a java array list object, not arrayvar tables = util.getTables();gs.print("Java list: " + tables);//what is the tables objectJSUtil.logObject(tables, "tables");

//enumerate java array listfor (var i=0; i < tables.size(); i++) { gs.print(tables.get(i));}

–  We could convert the array list to an array whenever we need it but it would be nice to change the getTables method to return an array

–  Modifying an out-of-box script include is never recommended

***  Script:  Java  list:  [cmdb_ci_server,  cmdb_ci_computer,  cmdb_ci_hardware,  cmdb_ci]  ***  Script:  Log  Object:  tables      Java  Object:  [email protected]  ***  Script:  cmdb_ci_server  ***  Script:  cmdb_ci_computer  ***  Script:  cmdb_ci_hardware  ***  Script:  cmdb_ci  

Page 39: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 7 – Extending Script Includes •  Try it

–  Let’s first look at the TableUtils script include

initialize: function(tableName){ this.tableName = tableName; },,

getTables: function(){ var tables = Packages.com.glide.db.DBObjectManager.get().getTables(this.tableName); return tables; },

•  There’s another script include we can use to convert java objects to javascript, that’s “j2js”

Page 40: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 7 – Extending Script Includes •  Since we don’t want to modify the system script include we’ll create our

own. We could make a full copy but that would be a waste, when we can extend the class and leverage everything that’s already in place.

•  Create a new script include for the MyTableUtils class –  Extending can add to or replace methods from the parent class

var MyTableUtils = Class.create();

MyTableUtils.prototype = Object.extendsObject(TableUtils, { getTablesArray: function() { var tables = this.getTables(); return j2js(tables); },

type: "MyTableUtils"});

•  Save the record so we can test it

Page 41: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 7 – Extending Script Includes •  Return to background scripts and call the new class

var util = new MyTableUtils("cmdb_ci_server");//call our new methodvar tables = util.getTables();gs.print("Java list: " + tables);JSUtil.logObject(tables, "tables");gs.print("");var tablesArray = util.getTablesArray();gs.print(tablesArray);JSUtil.logObject(tablesArray, "tablesArray");//what is util objectJSUtil.logObject(util, "util");

•  Notice that we didn’t need an initialize of getTables method in our class, we inherited those from the parent (“this”) object

Page 42: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 8

AJAX Debugging

Page 43: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 8 – AJAX •  Scenario: Use AJAX to lookup the number of available development

laptops when someone attempts to request one through the catalog

•  Components –  Catalog client script to submit AJAX request to server –  AJAX processor script include to perform the check and return the result to client –  Catalog client script to process the AJAX response and inform the user

•  Try it –  Go to the catalog and load the Development Laptop item –  Script runs on load to check inventory and alerts user with status from server

Page 44: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 8 – AJAX •  Review scripts

–  Review catalog client script “k11 Capacity Check” –  Review script include “k11 CatalogCapacityCheck”

•  Debugging options –  Log statements in script include –  Firebug to inspect payload to/from server –  Manual client script testing from javascript executor

Page 45: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 8 – AJAX •  Try it

–  From the development laptop catalog item page start the javascript executor <Shift><Ctrl><Alt><j>

–  Run the following script to make an AJAX request

var gajax = new GlideAjax("CapacityCheckAjax");gajax.addParam("sysparm_name", "checkDevCapacity");gajax.getXML(ajaxResponse);

function ajaxResponse(serverResponse) { alert(serverResponse.responseText);}

Page 46: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 9

Jelly

Page 47: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 9 – Jelly •  Scenario: In a jelly script such as a UI Page, I would like to know

which jelly variables are available and what the values are

•  Options –  For known variables you can write values to HTML output –  Use breakpoint tag to view all available variables in a given phase

•  Jelly in 30 seconds –  XML files executed on server and output as HTML to client –  Evaluated in two phases, {phase 1} is cached (content), [phase 2] for data –  Nested structures with variables typically being passed down (UI Page calls a UI

Macro)

Page 48: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 9 – Jelly •  Try it

–  Review UI page “k11_test” –  Notice the j:set and j2:set lines setting values for jvar_p1_test and jvar_p2_test

–  Review UI macro “k11_macro_test” called from the UI page –  Notice the references to the variables defined in the j:set and j2:set lines in the

UI page

–  Enable Debug Log so we can view of out of the macro breakpoints –  Navigate browser to /k11_test.do –  Examine the debug information –  Notice how our jvar_p1_test and jvar_p2_test only have value in their respective

phases

Page 49: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Debugging Examples Exercise 10

Display Business Rules

Page 50: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 10 – Display Business Rules •  Scenario: a client script needs to access data from a field that is not

displayed on the form

•  Options –  Add the field to the form view and hide it using a UI policy –  Use a client GlideRecord query using AJAX –  Use a display business rule to preload an object that is passed to the client

•  Display business rules are processed on the server before the record data is passed to the client

•  The “g_scratchpad” object is available for setting values in the rule and getting values on the client

•  Display rules can also change field data, similar to calculated fields since they display the new value but it’s not written to the database until you save the record

Page 51: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 10 – Display Business Rules •  Review business rule “k11 Exercise 10 Send data to the client”

on the problem table //get the record sys_created_by value and add to the client scratchpadg_scratchpad.created_by = current.sys_created_by;

//calculate the age of this recordvar age = gs.dateDiff(current.sys_created_on, gs.nowDateTime(), true);var daysOld = Math.round(age / 3600 / 24);g_scratchpad.days_old = daysOld;

•  Review the client script “k11 Exercise 10 - notify on old problems” on problem table function onLoad() { //get data from display rule scratchpad var createdBy = g_scratchpad.created_by; var daysOld = g_scratchpad.days_old;

if (parseInt(daysOld) > 30) { alert("This is an old record created by " + createdBy); }}

Page 52: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Exercise 10 – Display Business Rules •  Try it

–  Open the list of problems and find one that was created more than 30 days ago –  Notice the alert from the client script

Page 53: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Q & A

j_roberts

#know11 #servicenow

Page 54: ServiceNow Knowledge11 Advanced Scripting & Debugging Lab

Additional Resources •  SlightlyLoony blog (Service-now.com developer)

–  http://community.service-now.com/blog/slightlyloony

•  Wiki Script Portal –  http://wiki.service-now.com/index.php?title=Scripting_and_APIs

•  JavaScript book –  JavaScript The Definitive Guide (O’Reilly)

•  W3Schools script and HTML reference –  http://www.w3schools.com

•  Firebug –  http://getfirebug.com/