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!

Time Delay on Reverting and Reapplying

This is more of a fragment of a post than a legitimate post, but it still seem like something worth communicating. I’ll add additional information as my understanding solidifies.

I’ve been trying to track down a UI bug, and not having much success. Something is causing a comment to pop up on various UI Pages everywhere the UI Page incorporates a UI Macro.

I believe that the issue is stemming from reverting something to baseline as part of our next upgrade. Normally, I would expect that to be something that is quick and easy to isolate, but as nearly as I can tell, there is a delay between when a skipped upgrade is reverted back to baseline, and when it actually takes effect.

Part of that may have to do with a time delay in the reversions being pushed out to the various nodes that make up a given instance of ServiceNow, but there may also be more to it than that.

I reverted a script last week, and then went and checked the script subsequent to the reversion. It was showing as reverted on the upgrade history, but the actual script was still the changed version rather than the reverted version. I didn’t see the script actually revert until the next morning, which could mean that there is some kind of scheduled job that runs on a predetermined scheduled and the reversion didn’t take place until the scheduled job had run. It could alternately mean that there is a lag for some other reason and in that instance the reversion just took long enough that I didn’t see the change until the next morning.

I’ve also seen instances where the bug was occurring in spite of all of the reverted changes having been reapplied, and been ready to attribute the bug to something else entirely until it disappeared the next morning.

To summarize, I’m not sure if the UI bug I’m seeing relates to skipped upgrades being reverted or not, but I’m pretty positive at this point that reverted upgrades and changes being reapplied have a lag before they fully take effect.

Tracking a UI Macro Back To Where It Is Used

I’ve looked at a bunch of skipped upgrades at this point, but the group that has taken the most time has been the UI Macro skipped upgrades. Partly that is because there are so many of them, but it also has to do with the fact that I wasn’t quite sure how to track them back to the UI so that I could confirm whether or not there was something changing that I wasn’t anticipating from comparing the two different versions of the code.

After a good bit of effort around that, here is my process for tying things back to the UI.

1. Go into Studio and do a code search for the name of the UI Macro. UI Macros tend to be used either in other UI Macros, or in UI Pages.

2. If you have a UI Page pop up as using your UI Macro, then you can open that UI Page directly from inside of your code search. If you don’t have a UI Page pop up in the search results, pick one of the UI Macros that pop up, confirm that it’s really using your UI Macro, rather than something with a longer name that contains the name of your UI Macro, and then do a search on that UI Macro looking for a UI Page that contains it.

3. Once you have found a UI Page that contains your UI Macro, you can open up the definition–either from inside of studio, or by going to System UI > UI Pages. Towards the bottom of that page you’ll see a ‘Try It’ button that will allow you to open up the actual UI Page as seen by your users.

4. From there, you can compare a reverted version against your current, changed version, and testing out the functionality to make sure that you didn’t miss any breaking changes in your code review.

Version Tracking In ServiceNow

I’m currently reviewing a whole bunch of skipped upgrades at work, and had something that was perplexing me, so I thought that I’d share my findings with you.

I was seeing items that were coming up as being different from baseline, but when I looked at the version history on the item, it was showing one version from ~3 years ago that was the ‘current’ version of the script. There were also one or two versions with recent dates, but nothing before that current version.

All I could come up with was that no version history was being created until after a script was changed, and then once it was changed, only the modification was saved as a version in the history.

That accounted for the behavior I was seeing historically, but seemed like a sub-optimal way of doing things since it meant that you couldn’t easily compare your changed version to baseline–at least not before it popped up as part of a skipped change when upgrading from one version of ServiceNow to another.

I ended up submitting a ticket to HI Support asking for clarification on what I was seeing. It turns out that when you edit something, two versions are saved (the original and the modified version). That was what I’d been expecting to see, and honestly is something I should have tested before reaching out to HI Support, but that didn’t account for what I was actually seeing as I was looking at our skipped upgrades.

That, it turns out, is because ServiceNow had some problems with how they were doing version tracking ~3 years ago, so if you look at something that was first changed back in that time frame you don’t get the normal version tracking the way that it is done now.

Wait Conditions on Workflows

I recently ran into a problem. I had a workflow that did a number of things and then had a wait condition that was supposed to wait for a variable to change to a specific value before creating another task and moving on.

I had created a business rule that changed the variable on the catalog task that the workflow was attached to.

I’d tested all of the components and they were working correctly, but the workflow was getting hung up on the wait condition, refusing to move forward even after the business rule had changed the value of the variable.

As it turns out, the problem is that workflows aren’t constantly looking to see if the wait conditions have been satisfied. Instead, you have to nudge the workflow into re-evaluating the condition so that it can see that it’s time to move on.

First you need to create a new Workflow() object.

var wkfw = new Workflow();

Then you need to call the runFlows method on the workflow object. As far as arguments, the first argument needs to be the GlideRecord object for the RITM of the workflow you want to nudge. The second argument should be ‘update’.

All told, you would expect to do something like this:

// Grab the RITM object
var gr = new GlideRecord(‘sc_req_item’);
gr.get(ritmSysID);

// Refresh the workflow attached to that RITM
var wkfw = new Workflow();
wkfw.runFlows(gr, ‘update’);

New Variables on Old RITMS

One of the things that I learned during the process of rolling out that translation project is that when you add a variable to a catalog item, ServiceNow doesn’t go back through and retroactively add the new variable to existing RITMS.

In hindsight, that makes a lot of sense. The new variable might be mandatory on new RITMS, so if you were to add it to old RITMS, you’d have to either gather that new information for all old RITMS relating to that catalog item (likely time intensive, and potentially impossible), or you’d risk some of the core logic falling over when it came across mandatory variables an a RITM that hadn’t ever been filled out.

Unfortunately, not operating with the benefit of hindsight, I initially had thought that the lack of a link on old RITMS to the variables I’d created meant that the new RITMS would likewise not have a link between the RITM and the variable until I populated the variable.

Since that wasn’t the case, I ended up having to re-tool a couple of aspects of the translation logic as it related to translating variables.

Now I know better.