How to Identify Duplicate Records by Multiple Fields in ServiceNow

I have some records in a table which are duplicates. In this case, I can only identify “duplicate records” by whether several fields are identical; not just one. For example, let’s say I want to identify Incidents where the Short description, Assignment group, and Assigned to user are all the same. If only one or two of those fields match, but one of them is different, then the records are not duplicates. The’re only duplicates if all three fields are the same.

Is there any way to accomplish this with a script? Maybe by using GlideAggregate?

Thanks for your question, and indeed, there is a way to identify duplicate records based on multiple matching fields in a script in ServiceNow!

At first glance, you might think that the GlideAggregate APIs do not support any direct mechanism by which to identify duplicate records across multiple identical fields. However, there is a way!
By getting just a smidge clever, we can call the .groupBy() API method multiple times, in combination with the .addAggregate() and .addHaving() methods, to accomplish our goal of identifying duplicate records with more than one field that are identical.

Read on to learn more!

Read more

How to Merge Personal & Company ServiceNow Accounts

If you got your ServiceNow certifications or made progress in courses on NOW Learning using a ServiceNow partner or customer account, you may find that when you move on to another company, you no longer have access to those certifications or training progress. This can be frustrating, and unfortunately the process for migrating your certifications and progress from an account linked with your business email to your personal account is not always clear. Googling the question (at the time of writing), I found that the top several results were from old ServiceNow Community articles that are either no longer accurate, or perhaps never were.

This ServiceNow Pro-Tip article was inspired by a thread on the ServiceNow Developer community Discord server, and aims to give you an up-to-date and accurate answer as to how you can merge your old corporate ServiceNow / NOW Learning account from your ServiceNow partner or customer business email into your personal account, so you can retain your certifications and progress even after you’ve left the customer or partner company. If ServiceNow changes the process by which this is done (again) and you notice that this article becomes outdated, please leave a comment below and let me know the updated process so I can update this article and keep folks informed.

Read more

5 Lessons About Programming From Richard Feynman

I believe that Richard Feynman can teach ServiceNow developers (and any software developers) a great deal - about physics, sure; but also about our own discipline.

I'm something of a physics nut myself (insert Spider-Man meme here), which has led me to something of an obsession with Richard Feynman. His work, of course (I've even got a Feynman diagram tattooed on the back of my neck), but also his life and upbringing. I'm interested in how someone like Richard Feynman was raised, and what lessons can be taken about how to raise children to become people with his best qualities. Qualities like intellectual curiosity and earnest, unabashed, confident-yet-humble exploration.

I once talked about the importance of confident-yet-humble exploration of new topics on a podcast with Robert Fedoruk and Cory Wesley. You can jump straight to the relevant time-code in that episode if you're interested in hearing it, here. (https://perspectives.snc.guru). This is a topic about which I am deeply passionate. I strongly believe that if we had more people with the sort of confident and humble intellectual curiosity of Richard Feynman, the world would be a much better and better-off place.

So, to that end, here are a couple of lessons I've taken about software development, from the late great physicist, Richard Feynman.

Read more

Managing Instance-Specific System Properties for Dev/Test/Prod in ServiceNow

While watching this video by the venerable Jace Benson, I was inspired by an idea presented around the 4-minute mark: a more effective way to manage instance-specific System Properties. So inspired was I, that I decided to not only adopt his suggestion, but to write a little tool to handle it for me as well! I call this tool "Local Properties". 'Local', here meaning "instance-specific"; properties which should have one value in one instance (such as your dev environment), and a different value in a different instance (such as production).

As many developers will know all too well, this is a problem that we face often: How do you use one property value in one instance and another value in another instance, without risking poisoning the data in the higher instance just by modifying the value in a lower instance (and perhaps not even realizing that it's been captured in your update set)?

In this article, we're going to discuss the idea that Jace presented to solve this problem in a robust and elegant way, as well as a free tool that I've built to handle this for you!

Read more

5 Ways to Check your ServiceNow Instance for DANGEROUS CODE in Less Than 5 minutes

Your ServiceNow instance DEFINITELY has DANGEROUS CODE executing in it RIGHT NOW, causing performance issues, unexpected behavior, and hiding records from people who should be able to see them (including you)!

This isn't a fear-mongering tactic; it's a fact we all overlook - until it's too late.

In this article, we'll unveil the top five quick and efficient methods to uncover this concealed, risky, and performance-degrading code in your instance. But that's not all - we'll also shed light on other lurking risks that could be silently sabotaging your instance's performance or security - even as you read this!

Read more

Your ACLs and Business Rules are Broken (Here's How to Fix Them)

“My ACL requires a given role. A user has that role, but is still failing the access check. The ACL debugger says that the ACL script is what’s failing, but my ACL is not “Advanced” and there’s no script field! What is going on??”

Even when the "Advanced" checkbox is unchecked on your ACLs or Business Rules, the code in the "Script" field is still executing and it is still impacting the behavior of the ACL/BR (and impacting system performance and security)!

In this article, we’ll discuss an issue with “Advanced” ACLs and Business Rules (or non-advanced ones that behave as though they’re advanced/scripted).
This confounding behavior can very often lead to odd, unexpected, and nearly-impossible-to-troubleshoot behavior in the ServiceNow platform.

At the bottom of the article, you’ll find a free tool to solve these problems, and provide a better experience for developers and administrators in your instance!

Imagine you start creating an ACL (or a Business Rule for that matter). You begin by checking the Advanced checkbox, and writing some code to check if certain conditions are met. If so, your code then checks if the user has some specific role.

Before you even finish writing your script, let alone optimizing it, you smack your forehead and realize that you can just use the condition builder and a simple role-check for this ACL. No script necessary!
So, you set the condition field, add a role to the ACL, and un-check the Advanced checkbox.
The “Script” field disappears from the form, and you’re back to looking at a simple ACL, configured exactly as you wanted it.
All done, right?

Bad news, chum. Un-checking that checkbox did precisely nothing, aside from hiding the Script field. That script is still going to execute every time your ACL is triggered! This can have massive, detrimental impact on system stability, security, and performance…

Read more

ServiceNow Developers: BE THE GUIDE!

Every ServiceNow developer, administrator, and architect has at one time or another, got a requirement from their client that they know is bad-practice, silly, or sub-optimal.

I often come across developers in the ServiceNow communities (such as the ServiceNow Developer forums, Discord, or Telegram groups), having conversations like this:

How do I do X?
Why would you want to do that? What’s the goal?
Because that’s the requirement from the client.

Even when told that what they want to do is technically impossible, some will refuse to go back to the client and tell them that.
It’s as if people sometimes can’t fathom telling a client “that’s not possible but, if you tell me why you want to do it, I might be able to find a better way”.

In this article, we discuss how to approach these situations and what it means to be the guide as a ServiceNow developer.

Read more

A Faster, More Efficient Client-side GlideRecord (Free tool!)

EfficientGlideRecord is a client-side API class from which you can perform asynchronous client-side GlideRecord-style queries while maximizing performance (eliminating the negative performance impact of using the client-side GlideRecord object) and without having to create a separate GlideAjax Script Include!

Every senior ServiceNow developer knows that client-side GlideRecord queries are slow and inefficient, and that it's far preferable to use a GlideAjax call. However, GlideAjax can be a REAL pain to implement. I've got an entire article about using GlideAjax from both a client and server perspective.
Even I have to look up my own article from time to time to remind myself of the correct patterns when I need to use it, and I groan every time I think about having to create yet another Script Include just to handle this one little use-case in this unique application scope or something.

A couple days ago, I was whingeing on the ServiceNow Developers Discord about the poor performance (and inaccurate documentation) of the client-side GlideRecord API.
I was wishing there was something better that didn’t require me to make a whole separate Script Include just to query a single record from the database and get the value of a few fields on that record in my Client Script.

Unfortunately, that’s just the way it is. Client-side GlideRecord is massively inefficient, far too slow, and returns way too much unnecessary data to be used commonly in production code. GlideAjax is simply the best and most efficient method for looking up data from client-side scripts.

At least, it wasuntil now!

After searching for a better solution for another couple of hours, I finally decided:

So, I did. And now I’m sharing that solution with you!

This consists of only a few files: A client-callable Script Include that does the back-end work for us, and a Global UI Script that acts as the client-side GlideRecord alternative (which I very creatively named EfficientGlideRecord). There is also a "portal" version of the same UI Script.

Aside from the fact that you'll specify only the fields you want to retrieve from the database for maximum performance (see examples in the API documentation), this is otherwise a near-perfect drop-in replacement for the client-side GlideRecord class; meaning that in the vast majority of cases, you'll be able to take your existing code, change the word "GlideRecord" to "EfficientGlideRecord", call .addField() for each field you want to retrieve, and that's it - you're done!

You might be wondering: "Okay, that's not too much work. I could do a code search for client-side code calling GlideRecord and get a performance and user-experience boost by replacing it with EfficientGlideRecord and adding any fields referenced in the callback function... but just how much performance improvement are we talking about here? Is it actually worth it?"

Oh my sweet summer child... even I was baffled when I did my performance testing, at just how inefficient the client-side GlideRecord is, and by just how much performance could be improved with EfficientGlideRecord.

As you can see in the Performance section (or in the image below), with the fastest internet, performance was improved by 80% (from nearly three full seconds, down to about half a second). For larger queries by users with a slower 1-10Mbps internet connection, performance was improved by as much as 93% - from ~71,700 milliseconds, down to ~5,100ms.

Read on to learn more, see usage examples, and download this free tool as an Update Set!

Read more (+ full API documentation)

Animated Loading Message & Collapsible Details on ServiceNow Form or Field (Client-side)

I recently found myself in a bit of a sticky pickle in ServiceNow. I was building a client-side UI Action which needed to call a Script Include via GlideAjax.
The server-side component of that script would then call a REST API and retrieve some data.
The data would be transformed and then returned to the client to be displayed in the form.

This caused two major issues:

  1. The response could take a while, so it looks for several seconds as though clicking the button did nothing.

  2. When the response did arrive, there could potentially be a lot of data to display in the form message.

As you can see in the gif above, I was able to solve both issues with a fancy bit of code. And now I’m gonna share that code with you! How magnanimous, right? Right?!?

This article will tell you how I solved them, and provide you with the code I used (made fully modular so you can customize its behavior for your own situation). You can then include those functions in your Client Script in order to achieve similar functionality, with only a couple of lines of code!

Read more

Using .addJoinQuery() & How to Query Records with Attachments in ServiceNow

Here’s a common question:

“How do I use a scripted GlideRecord query to get all records in a given table that have attachments?”

Often, people in the Community Forums will suggest querying the table, iterating through every single record, running .hasAttachment() on every single one, and adding those records to a list if that returns true.

Or, they might suggest querying the sys_attachment table, querying every attachment associated with the target table, pushing every unique value from the attachment record's `table_sys_id` field into an array, then using that array to query the target table with something like grMyRecord.addQuery('sys_id', 'IN', arrRecordsWithAttachments.join(','));.

However, these solutions are quite slow and not exactly ideal. Instead, consider the use of GlideRecord's .addJoinQuery() method.

Consider the following code…

Read more