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.

Underlying Catalog Tables (ServiceNow) & An Update

In a past position, I went to the effort of hunting down and documenting the underlying tables that support catalog items, requests, request items, tasks, and the variables.

I’ve moved on from that position though, and no longer have access to those notes. As I started to re-pull that information, I found this graphic, which shows how that tables are related to each other.

I found it originally on this post, and it was originally created by Julian Hoch.

I thought I would pass it along in case any of my readers found themselves needing to know what tables to reference when coding against that area of ServiceNow.

In other news, the guided tour bug that I reached out to HI Support about has been turned into a problem so that they can get the right group working on resolving it.

 

Catalog UI Policy Bug?

A quick update on the guided tour bug that I reported a while ago. I’ve been back and forth with HI support several times, and during my last call with them we got them to the point of being able to re-create the bug on a consistent basis.

It appears that the bug (callouts not working on the submit button) only kicks in if you populate an intro and conclusion to the tour. It’s possible that just one of those two (intro & conclusion) is the issue. I didn’t test beyond that.

I found what feels like a bug, but which could just be me trying to use the system in a way that it wasn’t designed to be used.

If you go into a catalog UI policy, it gives you the option to change the catalog item that the UI policy applies to. I did an insert and stay on several UI policies, copying them from one catalog item to another catalog item that had the same variables.

I thought I was being clever and saving myself a bunch of time, but after doing that, none of the catalog UI policies (the UI actions) worked.

My best guess is that the variables on the two different catalog items had the same names, but different sys ID’s. So they look like the same variables, but aren’t actually the same variables. I haven’t had a chance to test that though so I’m not 100% sure that’s the cause.

Troubleshooting UI Policies

My last post covered some of the issues I’ve had to troubleshoot with variables lately, but didn’t cover the strategy for doing so.

When troubleshooting UI Policies, often the best thing to do is simply to deactivate all of the policies and then turn them on one at a time until you see the behavior that you’re trying to stop.

Sometimes, depending on what you’re seeing, turning them off one at a time until you see a particular behavior start or stop is the way to go.

Really, when bug hunting, it’s always best to look for strategies that allow you to pin the bug down to a specific section of code. Generally, if you don’t find the bug right away, then it relates to something that you either don’t understand well, or which you understand incorrectly. By eliminating big chunks of code, you reduce what you have to look at to something that is much more manageable.

That drastically improves your odds of figuring out what is driving the bug. It’s a strategy that I’ve learned, forgotten, and then relearned again. I tend to use it instinctively until I run into a new tool, application, or technology. Then, for some reason, I seem to forget to bring the principles with me that worked so well with previous tools and technologies.

A big hat tip to my coworkers Kim and Tatiana for reminding me the right way to go about debugging something. Hopefully it sticks for the next novel situation I find myself in.

ServiceNow Variables

I’ve been working a lot with variables lately. Here are some things that I’ve learned that either weren’t in my classes up to this point, or which didn’t stick for me when my classes covered them.

1. If a variable is refusing to be hidden, check to see if it is mandatory. I can’t say categorically that mandatory variables can’t be hidden, but I’ve definitely seen instances where a variable refused to hide until after it was no longer mandatory.

2. If you have something that isn’t behaving the way you are expecting it too, check that you don’t have a container that isn’t closed out. That can cause behavior that has been applied to the container to apply to variables that you don’t realize are part of the container.

2a. It’s implied by 2. above, but worth being called out specifically. I’m used to more specific rules trumping more general rules. That isn’t how containers and variables work. Instead, the less specific (UI Policies applied to a container) trumps the more specific (UI Policies applied to the variables inside of the container). If you make a container mandatory, you can’t set one of the variables inside the container to not be mandatory. You would have to set the container to be non-mandatory, and then individually set the other variables mandatory.

 

They Need To Feel The Pain

By nature, I don’t like to be mean to people, or make someone feel bad. That predisposes me not to write blog posts that call someone out on something that they are doing wrong.

That being said, there are some things (actions or behaviors) that need to be described so that others can avoid making mistakes that could cause serious harm to their careers.

In a past position I witnessed a terrible dynamic between a founder and their development manager. The founder would go to the development manager with a feature request. The development manager would agree that the feature was a good one, but would raise concerns and highlight problems with the founder’s desired method of implementing the feature.

They would go back and forth for a while, and then the founder would say something to the effect of “I’m the boss, this is my company, do it my way”.

Which is of course the founder’s prerogative even if it’s the wrong decision.

The development manager would go off and build, or have built, the feature using the founder’s methodology. Subsequent to the feature going live, the very problems that the development manager had warned about would begin to surface, and the product would begin to suffer.

I’m not privy to the full history between the development manager and founder. I have some suspicions as to the cause of this dynamic, but I don’t know for sure what led to the subsequent behavior. In my opinion, the correct action to take would be to go back to the founder and say something like:

“We’re seeing problem ‘x’, which is the result of the decision to do ‘y’ while designing this feature. What do you want us to do next?”

or maybe:

“The system is breaking down because of ‘q’. I think we need to do ‘r’.”

Rather than doing that, the development manager would confirm to themselves that the problem was arising because of the issues that they had warned the founder about, and then the development manager would go off and ‘fix’ the code by stripping out the founder’s design and coding it the way that the development manager had wanted to write it all along.

The pros to that course of action:

The development manager avoided a fight with the founder.

The technical problems were solved.

The cons:

The founder became convinced that he could ignore the advice of the development manager who was the actual domain expert when it came to developing software. Rather than making a decision to over-ride the domain expert and then feeling the pain from making a bad decision, the founder became convinced that there was no need to listen to subordinates who disagreed with the founder.

In effect, the founder was always right and everyone else was always wrong. The founder would be cautioned against something, do it, and then as nearly as the founder could tell there were never any consequences for having ignored the domain experts in the company.

The issues that the domain experts cautioned the founder about never materialized, which meant that the founder either had to lose faith in the domain experts, assume that the founder was somehow infallible, or some do some combination of the two.

Secondary effects of this decision by the development manager included:

Lengthened development cycles (things were essentially being built twice).

Insufficient focus on technical debt (other problems that the founder had been warned against never materialized, therefore there was no reason to worry about big data problems or other technical debt).

My takeaway from watching this dynamic over an extended period of time is that you should always let people–especially people above you–feel the pain of their decisions.

I think that human beings who are drawing a paycheck have a moral obligation to warn our managers when we see a decision being made that will have negative consequences. How far you go on something like that is a judgement call based on your personal circumstances. The companies that most need someone to stand up and take a strong position against a bad decision are usually the companies that will make an employee suffer the worst consequences for taking that kind of position.

Depending on your role, seniority, and the consequences of the bad decisions being made, you may or may not want to get out of that company as soon as it becomes evident that the bad decision is going to be made in spite of your warnings.

If you stick around though, it is vital that you let people feel the pain from that bad decision. If you don’t, you’re undercutting your credibility and signing yourself up for more of the same.