Clearing Your ServiceNow Cache

This week I had an instance where I created a custom table, and then had to come back and add an additional field/column to it. After doing so, I could no longer get the table to display in list view.

Other users were still able to see the table and the data on it, so I knew that it was still there.

In the end, running cache.do in the application navigator did the trick of clearing my cache and allowing me to see the table.

ServiceNow Closing a GlideDialogWindow From a Script

In my previous use cases where I needed to use a UI Page as a modal on a form from inside of ServiceNow, I was just displaying information.

That meant the job of closing the modal/UI Page rested squarely on the shoulders of the user.

In my most recent project (unfortunately something that will have happened months previously by the time this post is published), I needed to have the UI Page be close automatically after the user clicked on a button.

The proper line of code to close a dialog window is:

GlideDialogWindow.get().destroy();

That was fairly easy to find, but I was surprised to find that you can’t just call that anywhere from inside of the client script on the UI Page.

I’ve seen in the past some instances where the call stack inside of ServiceNow doesn’t seem to behave quite the way I would expect it to based off of my experience with other JavaScript environments. I can’t point to any specific examples, or remember for sure what I was working on when I ran into the odd behavior, but that recollection that I’d had problems previously caused me to place the .destroy() call inside of my callback function.

(I was using a GlideAJAX to drive back-end behavior from the UI Page, which necessitated the use of a callback function to parse out the XML response from the GlideAJAX.)

It appears that you’ve got to place the .destroy() call inside of the main client script function inside of your UI Page for it to properly close out the UI Page.

In my instance, placing that .destroy() call after the .getXML(callbackfunction) call meant that the callback function had been cleared off of the call stack before execution flow got to the .destroy() call, so everything worked, but I was surprised that I couldn’t call .destroy() from inside of the callback function.

Troubleshooting Calling a UI Page from a UI Action

As I discussed in my last post, I’ve worked with UI Actions to call UI Pages previously. However, during this most recent project, I was seeing odd behavior where when I would click on the UI Action, the page would be redirected to the page where the UI Page is defined rather than just staying on the current page and popping up a modal.

Even more surprisingly, when I hit the back button to go back to the form from which I’d click the UI Action, I would see the UI Page pop up as a modal.

As it turns out, this behavior is caused when you haven’t defined the UI Action in question as being client callable.

So, if you ever have a UI Action that is redirecting to the UI Page rather than displaying the pop-up, double check that you’ve clicked the ‘client’ box on the UI Action definition.

The Context of UI Pages From GlideDialogWindow

I recently found myself needing to have a UI Action pop up a modal which would accept user input and then go perform various actions depending on what user input had been received.

I created the UI page, and then rendered it using something like this:

var dialog = new GlideDialogWindow(‘UI_Page’);
dialog.setTitle(“Page Title”);
dialog.render();

That is fairly basic, and is something that I’ve done previously, but something that I hadn’t realized before now is that in the client script of the UI Page, it’s possible to use g_form calls.

In essence, it appears that a UI Page (at least one called from a UI Action which is in turn called from a form) has access to the same context/namespace as the underlying form which was used to call the UI Action.

Now that I’ve written that down, I’ll remember it for the next time that I need to do something more complicated with a UI Page.

ServiceNow Copying Date-Times In A Script

On a recent project, I needed to copy some date-time fields from one record to another.

I was using a server-based script include to do the copying, and assumed that I would be fine with a:

newRecord.created_at = oldRecord.getValue(‘created_at’) kind of construction.

What I found in practice though was that the date-time field on the copied record was 6 hours different than the field that had been copied from the original record.

This struck me as likely being due to a GMT vs local time kind of issue. That didn’t make a ton of sense given that we should just be copying one number from the back end to another field, also on the back end. Logically, I wasn’t expecting it to do any kind of changing of either of those two numbers to account for the user’s time setting, but apparently I was wrong.

Construction like this:

newRecord.created_at = oldRecord.getDisplayValue(‘created_at’)

Is returning a new record where the date-time field matches the original.

My best guess at this point is that ServiceNow runs some kind of middleware anytime you save a date-time (even on the back end) which takes whatever the user inputs and converts it to GMT.

In the original code, this meant that I was pulling GMT out of the database on the original record, and then that time was being shifted 6 hours before it was saved on the new record.

By getting the display value of the old record, we shifted the GMT time to local time, and then passed the local time to the middleware function which shifted it back to GMT before saving the new record to the database.

In short, any time you want to copy date-times, you need to use a .getDisplayValue() on the field you’re copying in order to have the value being saved in the new field match up with the old field.

ES6 Spread Operator

One of the frustrations of being a ServiceNow developer is the fact that you don’t get to use all of the latest Javascript bells and whistles because the Rhino engine simple doesn’t support them.

It would be less of an issue if I was happy to live completely inside of the ServiceNow ecosystem, but I have things that I want to build outside of ServiceNow, so I’m faced with having to mentally switch back and forth from ‘old’ JavaScript to ‘new’ JavaScript.

One of the things that I’m trying to remember to use more often outside of my ServiceNow projects is the ES6 Spread Operator. I recently had a use case where the spread operator was perfect:

I was building an express route that was creating a new record in the many side of a one-to-many relationship, and since I had authentication in place that confirmed that the user was who they said they were, I didn’t want to make the user pass in their user id so that I could tie the new entry to the user (the ‘one’ side of the one-to-many relationship).

— Without Spread Operator —
// Create a new item
router.post(‘/items’,auth,async(req,res)=>{
    const item=new Item({
        name: req.body.name,
       description: req.body.description,
       weight: req.body.weight,
        owner:req.user._id
    })
    try{
        await item.save();
        res.status(201).send(item);
    }catch(error) {
        res.status(400).send(error);
    }
})

— With Spread Operator —

// Create a new item
router.post(‘/items’,auth,async(req,res)=>{
    const item=new Item({
        …req.body,
        owner:req.user._id
    })
    try{
        await item.save();
        res.status(201).send(item);
    }catch(error) {
        res.status(400).send(error);
    }
})

 

Without the spread operator, I have to manually assign each of the request body items that I want to be placed into the object that is ultimately saved as a new record or document in the database.

With the spread operator, I can just tell the system to break the request body into its component parts and then place those parts into my new object.

Using the spread operator is obviously less typing than the alternative. That isn’t a massive deal when it comes to a request that only has 3 key-value pairs, but could become a big deal on a much larger request.

More importantly, though is the fact that using the spread operator future proofs your code much better than the alternative. If I were to go back and add something to my items table, and the corresponding requests coming into my route, the spread operator will just grab that new data seamlessly and start saving it to the database. I don’t have to remember to come back and modify that route to allow for the inclusion of that new data.

You could have a problem with the spread operator resulting in user input that you weren’t expecting being saved into your database, so you’ll want to do some testing if you’re using the spread operator on something that is user input.

In my case, I confirmed that Mongoose is trimming off anything that isn’t established as part of my model for the collection, which means that the spread operator was the perfect solution for this problem.

 

 

ServiceNow: Logging From Inside a GlideAjax

I recently had a piece of functionality that wasn’t coming together, and while I eventually figured out the issue, I would have gotten there much more quickly if I’d known for sure what method of logging to use inside of GlideAjax, or even if it was possible to log from inside a GlideAjax or not.

I tried searching online to confirm whether I should be using client or server logging, and didn’t find anything, so for future Dean, and anyone else who might by searching for this, the body of a GlideAjax runs on the server side of things, so logging inside of a GlideAjax uses gs.log().

More Madrid Bugs

I’ve continued to pursue the Madrid UI bug with ServiceNow that I referenced earlier, but while that has been going on I’ve found some other bugs, shortfalls, and other changes that took me by surprise in the system.

1. Under London, the ITIL user didn’t have any ability to edit the manager of a group from the sys_user_group table. Under Madrid that seems to have changed. Give that most organizations will be using that field to grant some level of access not enjoyed by the average user, there is a good chance that you’ll want to go in and lock that back down.

2. With Madrid, you now have the option to put a regex directly on the variables in your catalog items. We were really excited about this feature, but if you put a regex on a variable that is mandatory, and then test on the back end (rather than the service portal) the red * indicating that the field is mandatory stays red even after you’ve filled in the field. It works correctly on the service portal, which is where the end users will be going to actually request items, but I’ve had stuff kicked back to me from UAT because of this issue.

3. If you place a regex on a variable and then put an onChange client script in place to change that variable, you can run into problems. For example, I was asked to put a regex on a variable to enforce a string being entered in one of two formats. Setting the regex so that either format was acceptable worked just fine, but I also wanted to put a script in place to change strings entered in one format over to the other format so that we’d have consistently formatted data inside of the database. After parsing through the string, changing some of the characters, and then joining the array back up into a single string, the string no longer passed the regex. I ended up going with a different solution to fulfill the requirement, so it’s possible that there is something there that I was doing wrong without realizing it, but at first blush it looked like the string should have been passing the regex.

ServiceNow Telephone Integration

I recently had the need to integrate a phone system with ServiceNow such that callers could input certain data (like an employee ID) while on the phone using an automated system, and then have the phone system hit a particular URL which allows the fulfiller answering the call to be taken right to a new incident with the caller’s information pre-populated.

If you ever need to tie your phone system to your ServiceNow instance, there is a good chance that you want this link:

The CTI Processing business rule specifically is where you likely need to go if you need to customize any of what the pre-built computer telephony integration functionality.

Built-in Translation Functionality For ServiceNow

I’ve written a bit about the translation project that I did for a client using the Google Translate API to dynamically translate incoming incident and request data.

I generally find that one of the more difficult part of most projects is figuring out what already built resources are out there that you can take advantage of.

That isn’t to say that the rest of the project is easy, necessarily, but for the most part, once I know what existing assets can be leveraged, creating the incremental improvements are usually pretty straightforward.

In the spirit of that, for anyone who might be coming at a translation-related project inside of ServiceNow, here are a couple of off the shelf translation assets that you may not know about already.

Firstly, the ability to create translations for existing field labels is a built in piece of functionality (I believe it only becomes available after you download one of the plugins for language translations (French, Spanish, etc.).

Once you’ve installed one of those plugins, you can add translations via the sys_translated table. It’s not dynamic (meaning that you have to put the values you want translated into the table before you need them, or write something of your own to dynamically populate that table), but it does create a much better experience for user who speak languages other than English.

The other bit of translation functionality that I leveraged in my project is the sys_ui_message table. Entries to this table are accessible using the built-in getMessage() function.

That allows you to put translations of common words or phrases into the table, and then pass the English value via your code and get back the translated value from the table.

I hope that one or both of those functions are helpful to one of my readers in the future!