Author: Peter Cawdron

ServiceNow & ReactJS

Technology Background

Like any enterprise platform, ServiceNow has a complex relationship with its underlying architecture. Originally, ServiceNow was built on Java using Jelly XML for server-side component rendering. For its time, this approach was cutting edge.

As the Internet matured and social media ramped up, Google developed a clever client/server binding language called AngularJS that allowed for dynamic HTML pages to be rendered. ServiceNow adopted this only to have Google discontinue AngularJS in its original form. ServiceNow’s implementation of AngularJS as found in the Service Portal is world-class, but unfortunately, the underlying technology is no longer actively supported.

At this point, the architects at ServiceNow sat back and took a long hard look at emerging technologies and trends among the tech giants. It would be fair to say they were once bitten, twice shy. In developing their Agent Workspace UI, ServiceNow settled on using ReactJS (with GraphQL for data management) because of its broad scale adoption across the industry.

ReactJS is used by Facebook, Instagram, Netflix, WhatsApp and Dropbox to name a few, so ServiceNow are on safe ground with this technology.

Implementing ReactJS In ServiceNow

Whereas with AngularJS, ServiceNow provided an online IDE for widget development, at the moment the only way to build a ReactJS application for ServiceNow is to work offline. Once built, your ReactJS file can be deployed to ServiceNow as a packaged application.

There are pros and cons to this approach. On the positive side, ReactJS applications can be deployed with little to no overhead from ServiceNow, making them astonishingly fast and scalable. The only con is you need your own Node JS environment and ReactJS development platform.

Why Use ReactJS?

Why would anyone develop a ServiceNow application with ReactJS?

The answer is:

• ReactJS is an industry standard and so there is a vast pool of experienced web developers to draw upon
• ServiceNow provides a highly-scalable platform for ReactJS
• ServiceNow has built-in granular data security and APIs to manage data access
• ServiceNow is extremely efficient at workflow management and integration supporting ReactJS

Rather than building and managing a full-stack service platform for a ReactJS app, your app can be deployed quickly and easily through ServiceNow. Given the amount of effort and due-diligence required to operate a full-stack service at an enterprise level, ServiceNow provides a convenient shortcut.

When it comes to ReactJS, ServiceNow is effectively operating as PaaS (Platform as a Service). Think of your ReactJS app as a beautifully designed architectural home. ServiceNow allows you to position it as a penthouse suite without the need to worry about the rest of the building beneath it.

Creating A ReactJS Application

We’re going to create a nice simple ReactJS application listing contact details.

I recommend using the Code Sandbox for ReactJS applications as it is easy to use and provides an instant preview of your work.

To keep things simple, I’m going to use the ServiceNow REST API for Tables as my data access point.

Once you’ve signed into the Code Sandbox you’ll be assigned to one of their temporary virtual servers. The first time you run the code below it will fail because of cross-origin resource sharing restrictions (CORS).

If you look at the console log, you’ll find your temporary virtual server name. From there, you can set up a CORS exception that will allow access to your instance. Once that is in place, the application will work properly.

Without getting into too much detail, about how ReactJS works, we’re going to set up two files, our core Apps.js and contacts.js. We’re going to create a new folder called components to hold our contacts.js template.

Notice how when I hover over the line src folder in the Code Sandbox I get options for a new directory and a new file. This is how I added /components/contacts.js

Let’s look at the code used to retrieve contacts from ServiceNow and display them using ReactJS.

App.js

import React, { Component } from "react";
import Contacts from "./components/contacts";

class App extends Component {
  render() {
    return <Contacts contacts={this.state.contacts} />;
  }

  state = {
    contacts: []
  };

  componentDidMount() {   
    //this is a sample web service you can test with
    //fetch('https://jsonplaceholder.typicode.com/users',{
    fetch(
      "https://{your-instance}.service-now.com/api/now/table/sys_user?sysparm_query=emailENDSWITH{your-email-suffix}",
      {
        withCredentials: true,
        credentials: "include"
      }
    )
      .then((res) => res.json())
      .then((data) => {
        console.log(data);
        this.setState({ contacts: data.result });
      })
      .catch(console.log);
  }
}

export default App;

As you can see, our Apps.js file refers to /components/contacts to get an HTML/ReactJS template. It also includes a simple REST call (fetch) that uses the ServiceNow Table API to retrieve information from ServiceNow.

To get this example to work, you’ll have to replace…

  • {your-instance} with your ServiceNow instance name
  • {your-email-suffix} with your organisation’s email suffix (ie, gmail.com, etc)


contact.js is our HTML/ReactJS template. It takes the data retrieved from the fetch and formats it for display. It’s pretty straight-forward and intuitive to read.

contact.js

import React from "react";

const Contacts = ({ contacts }) => {
  return (
    <div>
      <center>
        <h1>Contact List</h1>
      </center>
      {contacts.map((contact) => (
        <div class="card">
          <div class="card-body">
            <h4 class="card-title">{contact.name}</h4>
            <h5 class="card-subtitle mb-2 text-muted">
              Email: {contact.email}
            </h5>
            <h6 class="card-text">UserID: {contact.user_name}</h6>
          </div>
        </div>
      ))}
    </div>
  );
};

export default Contacts;

That’s it.

That’s a ReactJS application.

At this point, your ReactJS application should work. If it doesn’t, look carefully at the console log in your browser and check you’ve completed the steps listed above.

Deploying A ReactJS Application

ReactJS applications need to be packaged and deployed.

Code Sandbox integrates with Netlify to provide online packaging and deployment.

The deployment may take a few minutes.

Make sure you have a Netlify account (I use my GitHub account for all of these services so everything is centralized)

Once you’ve signed into Netlify, Click on the little download arrow to get your package ready for deployment to ServiceNow.

Deploying on ServiceNow is simple enough, but it is a little bit of a hack.

This advice may change over time as ServiceNow develops its offering further, but the sanctioned approach at the moment is to deploy ReactJS as stylesheets.

The reason for this is style sheets are resources that can be accessed without authentication. In essence, you separate your JS and CSS into different stylesheets and then reference them from an HTML page (such as a UI page or a portal widget). So long as ReactJS is listed as a dependency for that page, it’ll load in the background, recognize your React JS in the stylesheet and run accordingly.

For more detail on ReactJS deployment in ServiceNow, please refer to:


Have fun and happy coding!

Service portal simplicity

The introduction of the Service Portal, using AngularJS and Bootstrap, has given ServiceNow considerable flexibility, allowing customers to develop portals to suit their own specific needs.

While attribution depends on whether you subscribe to Voltaire, Winston Churchill, or Uncle Ben from Spiderman, “With great power comes great responsibility.” And this is especially true when it comes to the Service Portal. Customers should tread lightly so as to use the flexibility of the portal correctly.

A good example of this arose during a recent customer engagement, where the requirement arose to allow some self-service portal users the ability to see all the incidents within their company. This particular customer provides services across a range of other smaller companies, and wanted key personnel in those companies to see all their incidents (without being able to see those belonging to other companies, and without being able to update or change others’ incidents). 

The temptation was to build a custom widget from scratch using AngularJS, but simplicity won the day. Instead of coding, testing, and debugging a custom widget, JDS reused an existing widget, wrapping it with a simple security check, and reduced the amount of code required to implement this requirement down to one line of HTML and two lines of server-side code.

The JDS approach was to instantiate a simple list widget on-the-fly, but only if the customer’s security requirements were met.

Normally, portal pages are designed using Service Portal’s drag-and-drop page designer, visible when you navigate to portal configuration. In this case, we’re embedding a widget within a widget.

We’ll create a new widget called secure-list that dynamically adds the simple-list-widget only if needed when a user visits the page.

Let’s look at the code—all three lines of it:

HTML

<div><sp-widget widget="data.listWidget"></sp-widget></div>

By dynamically creating a widget only if it meets certain requirements, we can control when this particular list widget is built.

Server-Side Code

(function() {
                if(gs.getUser().isMemberOf('View all incidents')){
                                data.listWidget = $sp.getWidget('widget-simple-list', {table:'incident',display_field:'number',secondary_fields:'short_description,category,priority',glyph:'user',filter:'active=true^opened_by.company=javascript:gs.getUser().getCompanyID()',sp_page:'ticket',color:'primary',size:'medium'});
                }             
})();

This code will only execute if the current user is a member of the group View all incidents, but the magic occurs in the $sp.getWidget, as this is where ServiceNow builds a widget on-the-fly. The challenge is really, ‘where can we find all these options?’

How do you know what options are needed for any particular widget, given those available change from one widget to another? The answer is surprisingly simple, and can be applied to any widget.

When viewing the service portal, administrators can use ctrl-right-click to examine any widgets on the page. In this case, we’ll examine the way the simple list widget is used by selecting instance options.

Immediately, we can see there are a lot of useful values that could be set, but how do we know which are critical, and what additional options there are?

How do we know what we should reference in our code?

Is “Maximum entries” called max, or max_entry, or max_entries? Also, are there any other configuration options that might be useful to us?

By looking at the design of the widget itself in the ServiceNow platform (by navigating to portal-> widgets), we can scroll down and see both the mandatory and optional configuration values that can be set per widget, along with the correct names to use within our script.

Looking at the actual widget we want to build on-the-fly, we can see both required fields and a bunch of optional schema fields. All we need to do to make our widget work is supply these as they relate to our requirements. Simple.

{table:'incident',display_field:'number',secondary_fields:'short_description,category,priority',glyph:'user',filter:'active=true^opened_by.company=javascript:gs.getUser().getCompanyID()',sp_page:'ticket',color:'primary',size:'medium'}

Also, notice the filter in our widget settings, as that limits results shown according to the user’s company…

opened_by.company=javascript:gs.getUser().getCompanyID()

This could be replaced with a dynamic filter to allow even more flexibility, should requirements change over time, allowing the filter to be modified without changing any code.

The moral of the story is keep things simple and…

Don't reinvent the wheel

Our team on the case

Static Variables and Pointers in ServiceNow

When scripting in ServiceNow, be careful how you create your variables. If you refer to an object such as a gliderecord field/column, you are creating a pointer to the ever-present current value rather than a static value at a point in time. Perhaps an example will help explain…

In our fictitious example, Ranner is the head of marketing and wants to know the first and last person with a first name starting with “Ra…” Obscure, I know, but it will demonstrate the point.

So we develop a script we can test using the Background Script module in ServiceNow to check a subset of records to make sure our logic is correct. We grab the first value and the last after cycling through the table.

var userGlide = new GlideRecord('sys_user');
userGlide.addEncodedQuery('first_nameSTARTSWITHRA');
userGlide.orderBy('first_name');
userGlide.setLimit('10');
userGlide.query();
 
var i = 0;
var firstUser, lastUser;
 
while (userGlide.next()) {
 
if (i==0) {
firstUser = userGlide.first_name;
gs.info('The firstUser is ' + firstUser );
}
 
gs.info('Iteration ' + i + ' current user = ' + userGlide.first_name + '\t firstUser = ' + firstUser );
 
if (!userGlide.hasNext()) {
lastUser = userGlide.first_name;
gs.info('The last user is ' + lastUser);
}
i++;
}
gs.info('-----------------------------------------------');
 
gs.info('First user is ' + firstUser );
gs.info('Last user is ' + lastUser );

If you look at the output when this runs as a Background Script, you can see there are inconsistent results. The firstUser variable changes every time the gliderecord changes even though it was set only once at the beginning.

*** Script: The firstUser is Ra
*** Script: Iteration 0 current user = Ra firstUser = Ra
*** Script: Iteration 1 current user = Ra-cheal firstUser = Ra-cheal
*** Script: Iteration 2 current user = Raamana firstUser = Raamana
*** Script: Iteration 3 current user = Raamon firstUser = Raamon
*** Script: Iteration 4 current user = Rabi firstUser = Rabi
*** Script: Iteration 5 current user = Rabia firstUser = Rabia
*** Script: Iteration 6 current user = Rabin firstUser = Rabin
*** Script: Iteration 7 current user = Racahael firstUser = Racahael
*** Script: Iteration 8 current user = Rachael firstUser = Rachael
*** Script: Iteration 9 current user = Rachael firstUser = Rachael
*** Script: The last user is Rachael
*** Script: -----------------------------------------------
*** Script: First user is Rachael
*** Script: Last user is Rachael

The reason for this is although we defined our variable at the start, all we did was assign a pointer to the glide record, not a static value. Every time the glide record moves onto a new record, so does the value within our variable.

The solution is to make sure we’re only grabbing a value and not an object from the gliderecord, by adding .getValue() to our script

var userGlide = new GlideRecord('sys_user');
userGlide.addEncodedQuery('first_nameSTARTSWITHRA');
userGlide.orderBy('first_name');
userGlide.setLimit('10');
userGlide.query();
 
var i = 0;
var firstUser, lastUser;
 
while (userGlide.next()) {
 
if (i==0) {
firstUser = userGlide.getValue('first_name');
gs.info('The firstUser is ' + firstUser );
}
 
gs.info('Iteration ' + i + ' current user = ' + userGlide.first_name + '\t firstUser = ' + firstUser );
 
if (!userGlide.hasNext()) {
lastUser = userGlide.getValue('first_name');
gs.info('The last user is ' + lastUser);
}
i++;
}
gs.info('-----------------------------------------------');
 
gs.info('First user is ' + firstUser );
gs.info('Last user is ' + lastUser );

Now our results are correct

*** Script: The firstUser is Ra
*** Script: Iteration 0 current user = Ra firstUser = Ra
*** Script: Iteration 1 current user = Ra-cheal firstUser = Ra
*** Script: Iteration 2 current user = Raamana firstUser = Ra
*** Script: Iteration 3 current user = Raamon firstUser = Ra
*** Script: Iteration 4 current user = Rabi firstUser = Ra
*** Script: Iteration 5 current user = Rabia firstUser = Ra
*** Script: Iteration 6 current user = Rabin firstUser = Ra
*** Script: Iteration 7 current user = Racahael firstUser = Ra
*** Script: Iteration 8 current user = Rachael firstUser = Ra
*** Script: Iteration 9 current user = Rachael firstUser = Ra
*** Script: The last user is Rachael
*** Script: -----------------------------------------------
*** Script: First user is Ra
*** Script: Last user is Rachael

When working with glide records, be sure to use the getValue() to avoid headaches with pointers.

Understanding outbound web services in ServiceNow

*This blog was updated on 20 March 2018*

ServiceNow has the ability to manage both inbound and outbound web services, but as they’re handled slightly differently, they can be confusing.

The term “inbound” and “outbound” does not describe the type of HTTP method being used but rather the point of origin for the web service. For example, both inbound and outbound services can use GET and POST.

Inbound web services are designed to provide third parties with the ability to retrieve (GET) or update (POST) data in ServiceNow, while outbound web services allow ServiceNow to initiate a transaction with a third party (also using either GET or POST, etc.)

Although they are closely related, inbound and outbound web services are handled differently through the ServiceNow GUI even though they’re essentially the same under the covers. Most developers are comfortable with inbound web services because ServiceNow provides a walk-through wizard for them, but they struggle with outbound services, even though these can be handled in the same way.

If a third-party wants to send information to ServiceNow using web services, then an inbound web service will allow them to POST that information.

snow2

If ServiceNow wants to retrieve information from a third-party using web services, then an outbound web service will allow ServiceNow to GET that information. 

snow3

In both scenarios, the end result is the same—ServiceNow is populated with information from a third-party.

This tutorial assumes you have a basic knowledge of how to create applications in ServiceNow as we’re going to make an outbound web service to retrieve a weather report for use in ServiceNow.

To complete this tutorial, you will need to sign up for a free account with http://openweathermap.org/api and subscribe to the Current weather data.

Step One: Create an outbound web service

The external web service made available by Open Weather is:

http://api.openweathermap.org/data/2.5/weather?q=Brisbane,au&appid={yourAppID}

If you sign up for an account with Open Weather and view the results in a browser, you’ll get a wall of JSON data in response, but if you copy and paste this into Notepad++ using the JSON formatter plugin, you’ll see there’s structure to the data. This is important, as this will allow us to extract information later on. If you don’t have access to Notepad++ there are a number of online services that can also help, like https://jsonformatter.curiousconcept.com.

As you can see, the temperature is in Kelvin rather than either Celsius or Fahrenheit, as 301K relates to a balmy 28C or 82F.

Also, the date time (dt) is using a numeric format known as Epoch time, so we’re going to need to transform the results from our outbound web service before they’re going to be useful.

Creating an outbound web service is easy enough, simply provide the web service with a name like outbound_get_weather and the end point URL, and tell ServiceNow what to accept and what the content type will be.

Under HTTP Methods further down the page, you’ll see get, delete, put, post. Delete all but get as all we want to do is to get information from open weather.

Edit the HTTP method Default GET and add the query parameters for “q” and “APPID.” If need be, you can set the order in which you want these parameters to occur.

  • q is the query parameter for the city, so we’re going to set this to be a variable rather than a static value. Make this ${q}
  • APPID is a static value, so this can be hard coded to match the application ID you got from Open Weather

Also, notice I’ve added a Variable Substitution and set this to be Sydney,AU, which allows me to click test and see fresh results for Sydney.

 

This is important as when we get to our scripted REST web service, we want to be able to change q to refer to other cities as appropriate.

Click Test to confirm you’ve got everything working correctly.

Step Two: A Tale of Two Tables

Next, we’ll create a regular ServiceNow table to be referenced by users and/or other applications. This is where the information we retrieve is going to reside.

Make a table called current weather and give it a temperature column and a weather date time column.

Our second table is a staging table. This is where the raw results of our web service will reside.

When you make an inbound web service, ServiceNow automatically creates a staging table, but when it comes to outbound web services, you need to create a staging table for yourself and manually assign a transform map.

Be careful. You must extend the Import Set Row table to create a valid staging transform table for your web service.

 

Notice how our data types in the staging table match those we saw in the web service results, so the epoch date is being stored as an integer.

Step Three: Transform

Now we can set up the transformation from our staging table to the final table in ServiceNow. Under System Import Sets click on Create Transform Map and build the following transform.

snow9

Initially, there’s only one source field we can match against the target field, for the others, we’ll need to use transform scripts.

To convert Kelvin to Celsius, add a new Field Map as follows, using this script:

var Celsius = source.temperature - 273.15;
return Celsius;

snow10

To convert the epoch date to a date ServiceNow will recognise, add another field map using:

var regularDate = new Date(0); // 0 forces javascript to use an epoch date

regularDate.setUTCSeconds(source.weather_date_in_epoch);

var formattedDate = regularDate.getFullYear() + '-' + (regularDate.getMonth()+1) + '-' + regularDate.getDate() + ' ' + regularDate.getHours() + ':' + regularDate.getMinutes() + ':' + regularDate.getSeconds();

return formattedDate;

When you’re finished, your transform map should appear as:

snow12

 Step Four: Tying it all together

We’re going to use a scripted REST API to bring everything together, so under Scripted REST APIs create the following record.

snow13

The resource we’re developing here is going to be called outbound_request_for_weather and will require some scripting, but the basic logic is pretty simple.

snow14

The logic of our outbound request for the weather is…

  • Time the transaction and record that in the application log
  • Use the ServiceNow RESTMessageV2 library to undertake the web service
  • Delete any old records
  • Set a custom parameter to grab the weather for a specific location
  • Retrieve the results from the response body and add these to the staging table
  • Our transform map will then run automatically in the background and populate the actual table with results

Here’s the script I used.

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

var requestBody, responseBody, status, sm;

try{

                //Time the overall transaction so there's a record of how long our outbound webservice takes

                var startTimer = new Date();

 

                sm = new sn_ws.RESTMessageV2("outbound_get_weather", "default get"); 

                //sm.setBasicAuth("admin","admin");

                sm.setStringParameter("q", "Townsville,AU");

                sm.setHttpTimeout(10000) //In milliseconds. Wait at most 10 seconds for response from http request.

 

                var getresponse = sm.execute();

                 var responseBody = getresponse.getBody();

 

                //clear out old records

                var currentweather = new GlideRecord("x_48036_weather_current_weather");

                currentweather.query();

                currentweather.deleteMultiple();

 

                var gr = new GlideRecord("x_48036_weather_staging_current_weather");

                gr.query();

                gr.deleteMultiple(); 

 

                //Convert the response into JSON

                var JSONdata = new global.JSON().decode(responseBody);

 

                gr.setValue("weather_date_in_epoch",JSONdata.dt);

                gr.setValue("temperature",JSONdata.main.temp );

                gr.insert();

 

                //Post a message to the application log noting how long this activity took

                var endTimer = new Date() - startTimer;

                gs.info('***Weather updated in ' + endTimer + ' msec');

} catch(ex) {

                responseBody = "An error has occurred";

                status = '500';

}

})(request, response);

Notice how the JSONdata.main.temp matches the structure of web service results we saw earlier.

If we look at the current weather table, we can see our results.

snow15

If we look at the application log we can see how long this activity took.

snow16

This script can now be set up under the System Definition as a Scheduled Job and run as often as needed.

In summary, we built our outbound web service using the same components as found in an inbound web service.

snow17

One common question that arises when dealing with web services is, “What approach should I use?” The answer is… think about who is initiating the web service and what do you want to accomplish.

snow18

Our team on the case

Filtered Reference Fields in ServiceNow

One common requirement JDS sees when working with ServiceNow customers is the need to dynamically filter the available choices in reference fields. This can be useful in both general form development and record producers.

Consider the following business requirement:
A national charity wants to implement a feedback form for its staff.
As staff work across a variety of areas, it’s important to match staff with the correct department, so the correct department manager can be notified about the feedback.

The charity has provided us with some sample data for testing:

Departments

Filtered Reference Fields in ServiceNow 1

Department Staff

Filtered Reference Fields in ServiceNow 2

As this feedback form is available to anyone working within the charity, JDS has built a record producer to capture feedback using the Service Catalog within ServiceNow.

Filtered Reference Fields in ServiceNow 3

To limit the available choices to only staff within a particular department, we’ll need to use a script that is triggered whenever anyone starts typing in the field or accesses a value lookup for the variable “Who would you recommend?”
Although there are numerous ways to approach this, always look for the simplest option. Rather than calling a custom script, use the Reference qualifier field in ServiceNow to set up the relationship.

Filtered Reference Fields in ServiceNow 4

Normally, fields on a form can be referenced using current.fieldname but record producers within a service catalog are slightly different, and need a slightly more qualified reference of current.variables.fieldname.

Let’s look at the results…

If we select “Community Outreach” the list of staff available under “Who would you recommend?” is limited to Jane Brown and Sarah Smith.

Filtered Reference Fields in ServiceNow 5

If we select “Youth Action” the list of staff available under “Who would you recommend?” is limited to Matthew Jones and Sarah Smith.

Filtered Reference Fields in ServiceNow 6

ServiceNow is a powerful platform that allows for advanced customisations to ensure a good fit with business requirements.

ServiceNow performance testing tips

Although ServiceNow comes prepackaged with a wide array of prebuilt applications, it’s possible to extend these and develop entirely new applications, and this is where performance problems may arise.

Out-of-the-box, ServiceNow is a fast, robust, secure SaaS platform. ServiceNow is designed to be extended and modified, but customers need to understand those points where performance issues may arise.

Slow loading forms can be a source of user frustration and hinder user uptake. Forms are an area where performance problems can be encountered because customers need to implement additional layers on top of the standard system to incorporate their own business logic. These layers can also build up incrementally over time which can result in reduced performance from one year to the next.

It’s important to understand what business rules and scripts are executing, and in what order, when a record is loaded in a form. This will allow us to better understand where performance issues may arise.

ServiceNow Forms

 

As you can see from the diagram above, there are business rules which execute on the server and scripts which execute on either the client or the server. Both can be a source of performance issues if not managed carefully.

 

Where possible, synchronous scripts should be avoided as the user will be forced to wait for the network/server response to arrive before they can continue their work. As tempting as it is to use asynchronous scripts to enhance the information available to users on a form, this still requires additional communication across the network to ServiceNow. JDS recommends using asynchronous calls sparingly, as there are other means of preloading information, such as using the g_scratchpad.

 

There are four ways of dynamically incorporating additional information into a form in ServiceNow:

  1. g_scratchpad
  2. GlideAjax
  3. GlideRecord
  4. g_form

 

Most ServiceNow administrators are familiar with GlideRecords and g_forms, but these have the heaviest overhead from a performance perspective, as they retrieve all the fields from a particular record when only one value may be needed. To avoid performance issues, you should consider using the g_scratchpad object where possible.

 

What is the g_scratchpad object?
The g_scratchpad object is a simple way of pre-fetching values that are needed on a form. Avoid making additional server calls from the client by anticipating the need for information ahead of time.

 

g_scratchpad
Using the g_scratchpad object is easy.

 

The scratchpad is whatever you need it to be. You define the keys and values you want. Simply load up the g_scratchpad object with whatever information is needed by the form, and then refer to it from the form using Client Scripts.

 

Here’s an example from the ServiceNow Wiki.

Display business rule
g_scratchpad.instanceName = gs.getProperty('instance.system.property');
g_scratchpad.hasAttachments = current.hasAttachments();
g_scratchpad.createdBy = current.sys_created_by;

You can then use this information in your client script without the need for an ajax call.

Client Script
// Check if the form has attachments
if (g_scratchpad.hasAttachments)
// do something interesting here

// Check if this is TEST instance
if (g_scratchpad.instanceName == ‘TEST’)
g_form.setDisplay('test_field', true);

Sometimes, GlideAjax or other methods will be required when information is needed dynamically, but you should carefully consider whether the g_scratchpad can be used before looking at other approaches. JDS recommends developers consult ServiceNow’s own Client Script Best Practices article for more information on this topic.

Why performance test ServiceNow?
When dealing with custom business logic, performance testing ServiceNow can be extremely beneficial. In past performance tests JDS has completed for various multinational companies, JDS has discovered database issues, slow responses for certain forms and also discovered that users from different locations around the world could have an impact in response times. Finding database issues and slow response times prior to going live has allowed these companies to address the problems before launch, helping them achieve their goals of streamlining business processes rather than causing more frustration for employees.

Performance is an important part of the user experience, and is key to ensuring the uptake of ServiceNow within your organisation.

Tech tips from JDS

Straight-Through Processing with ServiceNow

How much time is your organisation wasting on manual processes?

What is the true cost of lost productivity?

Straight-through processing (STP) has long been recognised as the Holy Grail of business processes, as it promises to eliminate manual paper forms along with human intervention at the back end. By avoiding the duplication of effort, straight-through processing promises to drastically improve the speed and accuracy of business processes.

Although straight-through processing has been attempted by numerous enterprise applications, such as SAP, IBM and Oracle, the problem has been that no single system handles data collection in a consistent, comprehensive manner.

Single System of Record
ServiceNow is unique among enterprise applications in that it uses a single system of record with common/shared supporting processes, such as workflows and notifications. Although there are hundreds of tables in the ServiceNow database, they are all closely related, and are often based on the two core tables — CI (Configuration Item in a CMDB) and Task. In ordinary business terms, CI and Task translate into objects and actions—and ultimately, all business processes revolve around things/people, and actions applied to them.

Source: https://thisiswhatgoodlookslike.files.wordpress.com/2014/05/platform.png

By using a common architecture for all applications, ServiceNow avoids the problem of integrating with conflicting data structures/applications. In essence, everything speaks the same language.

Straight-through processing
ServiceNow has a single system of record, making it ideally suited to straight-through processing. ServiceNow has the flexibility to adapt to multiple different application requirements whilst leveraging common structures and components. For example, fleet car management, purchase orders, and timesheet entries are entirely different business processes, but in essence they deal with objects (cars/orders/people) and activities (driving/tracking expenditure/working hours), and have similar requirements (approvals, workflow, records management, notifications, common master data, etc).

Essentially, the ServiceNow Automation Platform allows different business processes to be captured without changing the underlying system.

JDS recommends deploying straight-through processing in an iterative manner, using an agile approach.

  1. Validate user input with the target system
  2. Digitise paper forms
  3. Straight-through processing
  4. Automation

By adopting an agile approach with implementation in phases, organisations can see incremental benefits throughout the project.

Phase One: Validate user input with the target system
For straight-through processing to be successful, ServiceNow needs to validate incoming information to ensure it’s compatible with the target system. To do this, ServiceNow forms need to be pre-populated with values taken from the core system.

Straight-Through Processing with ServiceNow 2

For example, organisational data such as cost centres and approvers would be integrated with ServiceNow overnight to provide defaults/selection values within ServiceNow form fields. This approach provides the best performance, as access to up-to-the-minute data is not typically required, and the data integration ultimately ensures the consistency and accuracy of straight-through processing.

Phase Two: Digitise paper forms
Once ServiceNow has default values to validate end user input at the point of entry, existing paper forms can be digitized.
In the first phase, the front-end will be transformed with forms which are pre-filled and built upon a responsive UI, whilst the back-end process is unchanged.

 

Straight-Through Processing with ServiceNow 3

 

Although it is possible to automate the entire business process at once, in practice, most organisations prefer a phased approach so they can manage change and reduce the risk of any inadvertent impact on their core system during this time of transition.
Note that this approach immediately has a positive impact on end users, as the old paper forms have been transformed and are now made available through a searchable and user-friendly service catalog, while back-end processes stay largely the same, avoiding any disruption to existing services. The organisation has the opportunity to introduce streamlined processing without causing upheaval in the back office.

Phase Three: Straight-through processing
Once the digitization of paper forms has been established, it is time to automate the process to introduce efficiency to the back office.

 

Straight-Through Processing with ServiceNow 4

As straight-through processing is often interacting with core systems associated with Finance and HR, JDS recommends establishing an approval workflow process. Instead of manually entering all the request information, back office staff now provide oversight and approval of straight-through processing.

Phase 4: Automation
There may be some business processes which involve multiple parties and integrate with multiple systems end-to-end that could be automated in their entirety, such as ordering of software or employee on-boarding. In this case, ServiceNow can streamline straight-through processing with the use of ServiceNow Orchestration.

Orchestration is implemented by workflows in ServiceNow, allowing JDS to configure complex processes that span multiple systems. These may include activities such as approval and follow-on tasks which utilise data outputs from a system called inside the workflow to determine the next action.

Straight-Through Processing with ServiceNow 5

How much is manual processes costing your organisation at the moment?

Think of how much productivity is lost because users are forced to fill out paper forms, or back office staff are required to enter information into multiple systems. By implementing straight-through processing with ServiceNow, JDS can help you streamline your business processes, saving time and money, while radically improving your customer satisfaction.

Splunk: Using Regex to Simplify Your Data

Splunk is an extremely powerful tool for extracting information from machine data, but machine data is often structured in a way that makes sense to a particular application or process while appearing as a garbled mess to the rest of us. Splunk allows you to cater for this and retrieve meaningful information using regular expressions (regex).

You can write your own regex to retrieve information from machine data, but it’s important to understand that Splunk does this behind the scenes anyway, so rather than writing your own regex, let Splunk do the heavy lifting for you.

The Splunk field extractor is a WYSIWYG regex editor.

Splunk 1

When working with something like Netscaler log files, it’s not uncommon to see the same information represented in different ways within the same log file. For example, userIDs and source IP addresses appear in two different locations on different lines.

  • Source 192.168.001.001:10426 – Destination 10.75.001.001:2598 – username:domainname x987654:int – applicationName Standard Desktop – IE10
  • Context [email protected] – SessionId: 123456- desktop.biz User x987654: Group ABCDEFG

As you can see, the log file contains the following userID and IP address, but in different formats.

  • userID = x987654
  • IP address = 192.168.001.001

The question then arises, how can we combine these into a single field within Splunk?
The answer is: regex.

You could write these regex expressions yourself, but be warned, although Splunk adheres to the pcre (php) implementation of regex, in practice there are subtle differences (such as no formal use of look forward or look back).

So how can you combine two different regex strings to build a single field in Splunk? The easiest way to let Splunk build the regex for you in the field extractor.

Splunk 2

If you work through the wizard using the Regular Expression option and select the user value in your log file (from in front of “undername:domainname”) you’ll reach the save screen.
(Be sure to use the validate step in the wizard as this will allow you to eliminate any false positives and automatically refines your regex to ensure it works accurately)
Stop when you get to the save screen.
Don’t click Finish.

Splunk 3

Copy the regular expression from this screen and save it in Notepad.
Then use the small back arrow (highlighted in red) to move back through the wizard to the Select Sample screen again.
Now go through the same process, but selecting the userID from in front of “User.”
When you get back to the save screen, you’ll notice Splunk has built another regex for this use case.

Splunk 4

Take a copy of this regex and put it in Notepad.
Those with an eagle eye will notice Splunk has inadvertently included a trailing space with this capture (underlined above). We’ll get rid of this when we merge these into a single regex using the following logic.
[First regex]|[Second regex](?PCapture regex)

Splunk 5

Essentially, all we’ve done is to join two Splunk created regex strings together using the pipe ‘|’
Copy the new joined regex expression and again click the back arrow to return to the first screen

Splunk 6

But this time, click on I prefer to write the regular expression myself.

Splunk 7

Then paste your regex and be sure to click on the Preview button to confirm the results are what you’re after.

Splunk 8

And you’re done… click Save and then Finish and you can now search on a field that combines multiple regex to ensure your field is correctly populated.

JDS releases VuGen tools

JDS toolsOver the past few years, JDS has developed a number of useful tools internally in support of performance testing and writing HP Business Process Monitor scripts. These tools simplify and automate some complexity of script writing by resolving some of the more mundane, routine aspects of scripting in VuGen. After refining these tools, JDS has chosen to share these tools with JDS customers and the broader HP community. These tools are intended to provide VuGen scripters with access to a set of utilities that are commonly used by JDS consultants.

 

Convert Web Vusers to Java

Converts C-based Web (HTTP/HTML) VuGen scripts into a Java-based virtual user

Reformat web_custom_request

Reformats a web_custom_request into a more readable form regardless of whether it is XML/SOAP, JSON or Form data

Data Format Converter

Converts common data formats to/from a variety of formats including HTML, Base64, URL encoding, Hexadecimal, Binary. This tool can also be used to calculate time since the epoch and MD5 or SHA-1 encryption.

VuGen Code Highlighter

Mimics the colours used by VuGen script-view, which is helpful when preparing documentation. Please note, this highlighter will work with a whole host of other languages as well.

 

JDS will be releasing more tools in the coming weeks