sabell2012
Mega Sage
Mega Sage

NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.

 

DIFFICULTY LEVEL: INTERMEDIATE
Assumes good knowledge and/or familiarity of Orchestration, Workflows, and Scripting in ServiceNow. Assumes having taken the class SSNF and has good intermediate level of knowledge and/or familiarity with Scripting in ServiceNow. 


Continuing in the vein of workflow looping I found that I wanted a better Turnstile Activity. One that would take a variable rather than a "hard-coded" integer. To do this would require modifying the out-of-the-box Turnstile Activity to accept a variable.

 

NOTE: BEST PRACTICE: Try to avoid modifying and saving back down over the top of an existing out-of-the-box anything in ServiceNow. Any future upgrade to the software will be skipped to preserve your changes. Always make a copy and use that instead.

 

We will be doing the following for this lab:

 

  1. Make a copy of the existing Turnstile Activity
  2. Modifying the Turnstile Activity to accept a variable of our choosing rather than an integer.
  3. Creating a workflow to demonstrate looping using our enhanced Turnstile Activity (we will be using the initialize activity from my previous lab.

 

Assumption: That you have worked with and created ServiceNow Workflows before. Also, you should probably play with this in your personal instance until you get proficient with the concept. Just saying.

 

NOTE: We are going to create all of our activities first and wire them all together as the last step.

NOTE: I highly recommend creating an Update Set to capture your enhanced Turnstile Activity so that you can port it around if you want. I have placed everything from this lab out on the share if you want to download it.

 

Lab 1.1 — Enhancing the Turnstile Activity

 

1. Navigate to Workflow > Administration > Activity Definitions. This will open the Activity Definitions list view.

2. Search for the Turnstile Activity, and click on the link to open the activity. This will open the activity definition form.

  1. Change the Name field to be: Turnstile (Enhanced)
  2. Right-Click on the form header to display the context menu.
  3. Click on Insert and Stay. Make sure you do this or you will be modifying the original! This will make a copy of the original activity that will be yours to modify. Otherwise you will "own" the out-of-the-box version, and it WILL be skipped on your next ServiceNow upgrade. If you do save down over the original simply revert to the previous version and try again.

 

sabell2012_0-1703690471080.png

 

d. Scroll down on the form and click on the Script tab.

e. In the Script field change script to the following:

 

// Workflow activity definition handler class
//
// Implement activity definition handling in the onExecute method
//
// Implement any event handlers for the activity definition as a method named 'on[event_name]'
//     For example, to handle the 'cancel' event, implement an 'onCancel' method
//

var Turnstile__Enhanced_ActivityHandler = Class.create();
Turnstile__Enhanced_ActivityHandler.prototype = Object.extendsObject(WFActivityHandler, {

    initialize: function() {
        var schpdName = 'iterations_' + activity.activity.sys_id;
        WFActivityHandler.prototype.initialize.call(this);
        if (!workflow.scratchpad[schpdName]) {
            workflow.scratchpad[schpdName] = 1;
        }
    },

    onExecute: function() {
        // implement activity definition code here
        var schpdName = 'iterations_' + activity.activity.sys_id;

        var iterCountVar = parseInt(workflow.scratchpad[schpdName], 10);
gs.info('---> iterCountVar: ' + iterCountVar); // debug
        var iterAllowedVar = parseInt(this.js(activity.vars.u_allowed_iterations), 10);
gs.info('---> iterAllowedVar: ' + this.js(activity.vars.u_allowed_iterations)); // debug
        if (iterCountVar > iterAllowedVar) {
            //Youve iterated too many times...stop iterating
            activity.result = 'cancel';
        } else {
            //Still iterating
            iterCountVar++;
            workflow.scratchpad[schpdName] = iterCountVar;
            activity.result = 'continue';
        }
gs.info('---> workflow.scratchpad[schpdName]: ' + workflow.scratchpad[schpdName]); // debug
    },

    type: 'Turnstile__Enhanced_ActivityHandler'
});

 

NOTE: I put the debug statements in to allow you to see what happens as the workflow executes

NOTE: If you look careful you will notice that the following line has been modified:

 

var iterAllowedVar = parseInt(this.js(activity.vars.u_allowed_iterations), 10);

 

The this.js(…) will take whatever variable is fed to it and convert it to the value contained in that variable. This will be important when we go to use the new activity in our workflow.

 

       e. Right-click on the form menu to bring up the context menu. Click Save to save the script change.

3. You will notice that there are no variables or conditions defined. These were not copied with our activity, and will need to be put back (with a very slight modification).

4. On the Activity Variables tab click the New button. 

5. Now go to the bottom of our Activity Variable. In Related Links click the Advanced View link.

6. Fill out the form with the following:

  1. Column Name: iterations
  2. Label: Allowed Iterations
  3. Active: checked
  4. Type: String  <- Here is our "slight" modification. Previously this was Integer
  5. Order: 100
  6. Max length: 100  <- This is important as we will be putting a variable in this field now.
  7. Calculation: delete everything; it should be blank
  8. Mandatory: checked
  9. Click the Submit button to save your new variable.

7. From the Turnstile (Enhanced) form Right-Click and bring up the context menu.

8. Click on  Configure > Related Lists and move Condition default -> Activity definition back into Selected and click on the Save button. No idea...for whatever reason, ServiceNow removed this essential list from the form!

9. Click on the Condition Defaults related list tab.

10. Click on the New button. We will be creating two new defaults.

11. Fill out the form with the following:

  1. Name: Continue
  2. Activity definition: Turnstile (Enhanced)
  3. Condition:
activity.result == 'continue'

d. Order: 100

e. Short Description: Continue iterating

f. Right-click on the form header to bring up the context menu and click Save to save your new Continue condition default.

12. Now change the form to the following:

  1. Name: Cancel
  2. Activity definition: Turnstile (Enhanced)
  3. Condition:
activity.result == 'cancel'

d. Order: 200

e. Short Description: You've looped too many times...cancel it...

f. Right-click on the form header to bring up the context menu and click Insert to save your new Cancel condition default.

 

sabell2012_1-1703692262650.png

 

You have now completed your new enhanced Turnstile Activity! Congratulations!

 

 

Lab 1.2 — Using the Turnstile Activity

 

1. Navigate to Workflow > Workflow Editor. This will open the workflow editor.

      a. In the Workflow Navigation column click on the "+" symbol to create a new workflow

2. Create a new workflow form

  1. Name: Enhanced Turnstile Example
  2. Table: Global
  3. Description: Demonstrate a new Turnstile Activity that will take a variable.
  4. Take all other defaults
  5. Click the Submit button to create the workflow

3. Navigate to Core > Utilities and drag out a Run Script Activity on to the desktop.

 

Here we will be initializing our loop. We will load a specified number of records from the Incident table. Store these into a scratchpad variable. The number of times to loop will be the number of records. We will start with 0 as the first number. Notice that there is a slight tweak to the count variable from what we did in the last lab. This is because the Turnstile is acting on the "end" of things and loops one more time than we would like. No biggy.

 

  1. Name: Initialize
  2. Script:

 

var identifier = context.name + '.' + activity.name; // introducing just a bit more sophistication!

var incidentRecords = new GlideRecord('incident');
incidentRecords.addQuery('state', '!=', 7); // closed
incidentRecords.setLimit(workflow.inputs.u_numberofrecords); // note that this comes from your inputs
incidentRecords.orderByDesc('number');
incidentRecords.query();

gs.info('---> row count: ' + incidentRecords.getRowCount()); // debug

var incident = {};
var incidentList = []; // this will be an array of objects
while (incidentRecords.next()) {
    incident = {};
    incident.sys_id = incidentRecords.sys_id + '';
    incident.number = incidentRecords.number + '';
    incident.assigned_to = incidentRecords.assigned_to.getDisplayValue();
    incident.short_description = incidentRecords.short_description + '';
    incident.state = incidentRecords.state.getDisplayValue(); // notice that we get the label
    incidentList.push(incident);
}

workflow.scratchpad.count = incidentList.length - 1; // the overall count available
workflow.scratchpad.incidentList = incidentList; // the list of incident objects
workflow.scratchpad.counter = 0; // our counter
workflow.scratchpad.message = ''; // the cumulative message

gs.info('---> [WF:{2}] Total number of records to loop: {0}, test value {1}',
    [workflow.scratchpad.count,	 
	workflow.scratchpad.incidentList[workflow.scratchpad.counter].number,
	identifier
]);

 

c. Click the Submit button to create the Activity

5. Drag out a Run Script Activity on to the desktop.

  1. Name: Compile Message
  2. Script:

 

Here we will save up a cumulative message which we will print out each time to the System Log (in the Do Work Script Activity). Note that we are reference the "current" incident record using our object array, and our counter. This is part of the magic!

 

var incident = workflow.scratchpad.incidentList[workflow.scratchpad.counter];

var message = gs.getMessage('[{0}] Number: {1} - {2} - {3}\n', [
	incident.number,
	incident.short_description,
	incident.assigned_to,
	incident.state
]);
workflow.scratchpad.message += message;

 

c. Click the Submit button to create the Activity

6. On the Workflow Core tab, navigate to Timers

7. Drag out a Timer Activity.

 

Here we will wait one second so that the logs are written down in order. Otherwise there is no need for this activity.

 

  1. Name: Wait a Sec
  2. Timer Based On: A user specified duration
  3. Duration: 1 seconds
  4. Click on the Submit button to create the Activity

8. Copy the Wait a Sec Activity (we will need two for our workflow).

9. Navigate to Core > Utilities and drag out a Run Script Activity on to the desktop.

  1. Name: Do Work
  2. Script:

 

var identifier = context.name + '.' + activity.name;

gs.info('---> [WF:{2}]\nLoop Count: {0} - Message so far:\n{1}',
    [workflow.scratchpad.counter,
    workflow.scratchpad.message,
    identifier
]);

 

10. On the Workflow Core tab, navigate to Utilities. You will now see your new Turnstile (Enhanced) activity present in the list!

11. Drag out a Turnstile (Enhanced) Activity on to the desktop.

 

We can now enter a variable instead of an integer! Cool huh?!

 

  1. Name: Loop Check
  2. Allowed Iterations:  
${workflow.scratchpad.count}

c. Click the Submit button to create the Activity

12. Navigate to Core > Utilities and  Drag out a Run Script Activity on to the desktop.

 

Here we will log down the final Message to the System Logs.

 

  1. Name: Log Message
  2. Script:

 

var identifier = context.name + '.' + activity.name;
gs.info('---> [WF:{1}]\nFINAL Message:\n{0}', 
	[workflow.scratchpad.message, identifier]);

 

c. Click the Submit button to create the Activity

13. Navigate to Core > Utilities and  Drag out a Run Script Activity on to the desktop.

 

Here we will increment the loop counter.

 

  1. Name: Increment
  2. Script:

 

workflow.scratchpad.counter++;

 

c. Click the Submit button to create the Activity

14. Wire everything up to look like the following:

 

sabell2012_4-1703695554155.png

 

15. Click on the Triple Bar (a.k.a "The Hamburger", or Tri-lipse) in the upper left of the Desktop, then click on Edit Inputs. We will use this to define a single test input variable for our workflow.

16. Add a new input variable:

  1. Type: Integer
  2. Label: Number of Records
  3. Column Name: u_numberofrecords
  4. Default Value: 5
  5. Click the Submit button to create the new variable.

17. Close the Workflow Inputs form.

 

Now we are ready to test our new Turnstile Activity!

 

 

Testing

 

1. Now click the Run Workflow button on the top right. The Start Workflow form will appear.

2. Click the Start button to run the workflow.

3. Accept the default of five loops.

4. The workflow will loop through five times and then exit.

 

 

sabell2012_3-1703695521772.png

 

5. From your ServiceNow browser tab Navigate to System Logs > All. This will open the System Logs list view.

6. Filter for all messages starting with --->

7. Order by date Created descending. You should see something like the following. There should be five entries showing the counting up from zero to four, then a "FINAL" message should be printed out with all of the entries.

 

sabell2012_5-1703696108064.png

 

And now you have your very own custom Turnstile Activity!

 

Enjoy!

Steven Bell.

 

If you find this article helps you, don't forget to log in and mark it as "Helpful"!

 

sabell2012_1-1703111089980.png


Originally published on: 09-29-2015 08:31 AM

I updated the code, fixed broken links, and brought the article into alignment with my new formatting standard.