Logging Objects in ServiceNow

I believe that I’ve got a post from a ways back talking about how to log an object in ServiceNow. Since then, I’ve realized that there are two much easier ways to log out on object.

You can stringify the object before trying to log it, or you can use the JSUtils.logObject() method.

Here is a quick demo script:

var myObject = {
“name”: “Object1”,
“number”: 1
};

var stringObject = JSON.stringify(myObject);
gs.log(“My Test. myObject: ” + myObject);
gs.log(“My Test. stringObject: ” + stringObject);
JSUtil.logObject(myObject);

Here is the output:

 

 

 

 

Here is the official documentation for the JSUtil.logObject method:

https://developer.servicenow.com/app.do#!/api_doc?v=newyork&id=r_JSUtil-logObject_O_S

Fields Being Added Automatically to Forms

Today (today when I am writing this–not today when the scheduled post will go live), I came across an interesting behavior in ServiceNow that I wasn’t expecting.

I had noticed previously that when you add a custom field to a table, that field is automatically added to the table’s form (at least one of the forms).

Today, I added a field to a table that is parent to a whole bunch of other tables. I had a passing thought that I should check the child tables to see if the field was added to them as well.

As it turns out, it is, but only under certain circumstances. It appears that if you’ve never opened a form up before, then the first time that you open the form up it has some logic that it follows to add some/all/most of the fields in the order that they were created.

So, if you’ve never opened up the form for a child table, and you add a custom field to a parent table, then when you open up the child form, it will have the new field on it.

However, if you’ve ever opened up that form, then adding a field to a parent table won’t impact the fields that are on the child table’s form.

A big thanks to Cory S. from the ServiceNow devs Slack channel for pointing me in the direction of how all of this worked!

User Criteria Idiosyncracy

A little while ago I needed to set up a new user criteria to restrict access to a catalog item.

As is my usual pattern, once I had set up what I thought was a valid user criteria, I tested my work by impersonating a user who shouldn’t have access to the catalog item and then attempting to access the catalog item.

Much to my surprise, the impersonated user was able to access the catalog item. I went back and checked my script on the user criteria and realized that I had a typo there which was causing it to authorize everyone.

I fixed the script, saved the user criteria, and then impersonated the user again so that I could confirm that they no longer had access to the catalog item.

Contrary to what I was expecting, they were still able to access the catalog item. After several iterations of making changes to the script and then checking the user’s access, I realized that the script had been working correctly from version 2 onwards.

The issue wasn’t with the script, but rather with the fact that ServiceNow caches the access somewhere. As nearly as I can tell, it checked the user criteria the first time that my impersonated user tried to access the catalog item, and then after that it just checked whatever flag it had saved off that indicated that the user had access to that catalog item.

When I pulled up another user–with identical flags to the first user, they were correctly barred from accessing the catalog item.

The next day, my first user was no longer able to access the catalog item, so it appears that some kind of scheduled job either clears out the caching or updates the caching to the latest user criteria on some kind of regular (probably nightly) basis.

 

Adding Images to an Email Notification (Inside of ServiceNow)

A little while ago, I needed to create a new notification. The best way to explain what I needed to explain on the resulting email was to include an image in the email.

Actually attaching the image to the email notification was a simple matter, but predictably, the image wasn’t caught in the update set.

I initially though that I was going need to go find where the image was stored in the table that contains all of the attachments, but that didn’t work.

Instead, the solution was simply to export the notification itself to XML, which was a little counterintuitive since everything else about the notification (other than the image) was picked up by the update set, but there you have it.

Exporting the notification to XML allowed me to easily move the notification and attached image up our development stack.

Adding and Accessing a System Property

As I’ve indicated in the past, I write this blog at least partially as a way of documenting things that I’ve figured out, but which I know I’ll need to refer back to at a future point. This is one of those things.

When programming my side projects, I use system variables on a regular basis. Having a constant in one spot where I can change it if something about my environment changes is hugely helpful. Likewise, it is very beneficial to be able to have one value for my dev environment and another value when the code is running on the production server.

Creating a system property is the equivalent thing in ServiceNow, and I’m grateful to my previous boss, Chris York, for showing me how to both set one up and then access it from inside of my server-side script include.

To create or modify a system property, go to:

sys_properties.list

Then, if we assume that I set up a system property that is named ‘deans.api.key’, to access it from inside of a server script, I would use:

gs.getProperty(‘deans.api.key’);

This would return the value of the system property, allowing me to assign it to a variable or otherwise use it.

Hugely helpful!

getXML() and getXMLWait()

I have a common pattern I use where I have a server-side script include that does all of the heavy lifting, which then subsequently needs to be accessed by something on the client script.

Using a GlideAjax script include allows you to take input from the client side of things and pass it to the GlideAjax which in turn passes it to your server-side script include.

This works well on the whole, but can run into problems if you have something on the back end that isn’t instantaneous–like an API call. In those scenarios, you can see instances where the client script has moved on and is acting as though it has the data from the server-side script include before the data is actually there.

In modern JavaScript I would handle that by using async/await, but it took a bit for me to figure out how to deal with it inside of ServiceNow.

The correct way to do that is with getXMLWait(), or by calling getXML() and then passing in the name of the function you want to run after the server-side stuff has run.

Note, you have to pass just the name, not the name and (), so if you had

function doSomething() = {

     console.log(“Hello World”);

}

and you wanted to add a callback to a getXML(), then you would use:

getXML(doSomething);

Determining what makes up a Performance Analytics Dashboard

This is going to be one of those posts that seem like common sense to some people, but I recently needed to figure out which reports made up a particular performance analytics dashboard, and I didn’t find anything that jumped out at me online.

It turns out that the way to find this out is to go to the list of dashboards (pa_dashboards.list).

Then click the ‘Launch Dependancy Assessment’ ui action. This will pull up a list of tabs and the reports that are on each tab, allowing you to find out what makes up the dashboard.

ServiceNow Workflow Scratchpad (Break)

I recently had a project where I wanted to use a looping workflow that would continue around the loop until some criteria was met.

For various reasons, I was going to find out whether or not a given loop was done before I actually reached the if statement that was designed to break the execution flow out of the loop and allow the workflow to move on.

Given that, it seemed sensible to to use the scratchpad to set a variable that I could then check against when it came time to break out of the loop. That would save me having to do a GlideRecord query at the decision point to determine whether or not it was time to exit the loop.

I wrote the code, and when the workflow detected that it had gotten to the point where the loop wasn’t supposed to continue, I set “workflow.scratchpad.break = true”, at which point my workflow broke and started behaving erratically.

It’s possible that something else was happening as a result of setting the break variable to true, but as nearly as I can tell, doing that actually dumped the values in the scratchpad, leaving me with undefined instead.

I’ve done some checking to try and see if that is documented somewhere, but haven’t be able to find anything to date. It makes sense that break could end up being some kind of reserved term given its use generally inside of Java and Javascript.

For now, use workflow.scratchpad.break in your workflow at your own risk.

NodeJS Testing Framework beforeEach() vs beforeAll()

I’ve been using the Jest testing framework in a side project. One of the areas I needed to test required that I populate data in my MongoDB database so that there was something for the tests to run against.

I had some debate in my mind between using beforeEach(), which does the database population step before each individual test is executed (once for each test), or using beforeAll(), which does the database population step one time before the tests are run collectively.

BeforeAll() seemed like the more efficient–and therefore quicker–way to do things because it would involve fewer calls to the database, but I ran into a circumstance where that was making writing a couple of the tests more difficult.

In testing however, I found that there wasn’t any consistent difference in speed between using beforeEach() and using beforeAll(). I don’t know if that’s because Jest is running the tests asynchronously and therefore the wait while the database is populated is mostly overlapping for each of the tests, or if Jest is doing something where it doesn’t actually run the beforeEach on tests that don’t read from the database, or if there is something else entirely going on there.

The key takeaway for me was that it didn’t matter (from a performance standpoint) whether I used beforeEach() or beforeAll(). As a result, I’ll be using beforeEach() because it makes writing tests slightly easier.