Service-now.com provides a very robust and simple way to manage your tasks and approvals (among other things) through its graphical workflow engine. It is very common to use graphical workflow to help facilitate some change management process within your organization. One common requirement in change management is to be able to cancel or close the change request at any time during the process. “Simple”, you say. “Just allow the user to change the value of the ‘State’ field to ‘Closed’.”
You would not be incorrect in saying something like that, but you would be forgetting about part of the problem with closing or canceling a change request or other task ticket. What if the attached workflow(s) still think that the change request and its associated tasks and approvals are still in progress? Should the attached workflow context(s) continue to run indefinitely? If your workflow doesn’t have a way to know about the completion of the change request then it will continue to run (or more likely just sit and be forgotten).
The answer to this problem is actually pretty simple. Service-now.com comes with several out-of-box workflow utility functions defined under ‘System Definition -> Script Includes’ that can be helpful in situations like these. While you don’t want to modify these script includes, it is probably a good idea as a Service-now administrator to become familiar with the tools and functions there. One of the functions in the ‘Workflow’ script include is called ‘cancel’. It can be used to cancel any running workflow activities for a given record. This script could be called from a UI action button, another workflow, or a business rule. You just need to be able to tell the function what GlideRecord should have its workflows canceled. The example below shows how you could create a business rule to cancel all running workflows for a given record if the ‘active’ field changed to ‘false’. The cancellation in the example below happens for the ‘current’ GlideRecord object (which is the current record being updated).
Cancel All Workflow Contexts for a given Record
Name: Cancel workflows
When: After
Insert: True
Update: True
Condition: current.active.changesTo(false)
Script:
new Workflow().cancel(current);
Cancel a Single Workflow Context (by name) for a given Record
You may also encounter situations where you don’t want to cancel all associated workflow contexts, just a single one, or all but one. Again, you can find the solution in the ‘Workflow’ script include by way of the ‘getRunningFlows’ and ‘cancelContext’ functions. The following script could be run from a business rule, UI action, or even within a ‘Run Script’ workflow activity. The example given here cancels any ‘Routine Change’ workflow contexts associated with the ‘current’ record.
var flows = new Workflow().getRunningFlows(current);
while(flows.next()){
//Check for associated workflows by name
if(flows.workflow_version.getDisplayValue() == 'Routine Change'){
//Cancel the workflow context
new Workflow().cancelContext(flows);
}
}
Thanks for this, it was very helpful. I was looking for workflow scripts in the wiki and couldn’t find any. I’ll bookmark this site! Cheers!
I’m glad you found something that works for you. Thanks for your comments. I’m hoping to continue to build out this site with useful content that might not be as prominent on other sites. Please use the ‘Ask The Guru’ link to post any suggestions for the site or content. I’d love to hear your suggestions.
What is the best practice to implement this? A business rule on the table? e.g. if task set to closed, then run. Or run as a job periodically? The example above shows query, then run the cancel method. If I were to implement it as a business rule what exactly would I call (just Workflow().cancel(current); )? let me know the best way to accomplish this.
You’re right, that was kind of vague. I’ve updated the document above to add a little bit more clarity. Probably the best way to implement this is in a business rule on the table where the cancellation takes place.
Hi Mark,
what if I don’t want the approvals to get cancelled, just the workflow?
as of now, all approvals even approved changed to cancelled. we need to know who approved or not in a change.
is this possible?
thanks
Alli
Hi Mark,
Is it possible to delete a workflow context from a business rule, We have situation, where if the user changes the environment we need to trigger a new workflow, the old one must be deleted.
Thanks
Arun
You can simply by performing a GlideRecord query. It’s probably better though to just cancel as shown above and then set the conditions on your other workflow so that it attaches when the environment changes.
Thank you Mark. I was considering modifying the current cancel workflows business rule or duplicating it with other conditions. I’m still tormenting myself on what should be common practice, i.e., I suppose a workflow could continue past active=false to kick-off another workflow, etc…. Maybe this is just too esoteric a thought path.
Hi Mark,
It is possible to modify this UI action and trigger any workflow once user click the button(UI Action).
I have a requirement where user move the status to more information requested by clicking the UI Action button, my plan is to create a simple flow and run it when someone click the UI Action rather than create flow with all combinations.
Thanks in advance.
ND
You can do that, but your business rule would still handle the cancellation part. The UI action would just set the form/field value that the business rule keys off of.
Hi Mark,
Thanks for reply.
What is the function I should use to trigger worklow. Is there is any document available which talks about all functions available for workflow.
I am looking for code to start workflow similar to
new Workflow().cancelContext(flows);
ND
You don’t use a function to trigger the workflow. You trigger a workflow by updating the record so that it meets the workflow conditions.
Yes..That’s what I am doing as of now. My workflow triggers when request move to “Assigned” and trigger emails. Problem here is one record can move to “assigned” more than one times and workflow will work only when request first move to assigned. I know other option would be modify the workflow but it is getting complex because we have many such status.
Hi Mark, you mentioned in the intro that the script include Workflow can be called also from UI action. What would be the syntax for there? I used same syntax as your example. But it didn’t work. The workflow is not canceld.
//Query for all executing workflows and cancel any running activities
new Workflow().cancel(current);
thanks in advance
That’s all you have to do. You’ve got the syntax correct. I just tested your code against a change request ticket in a ServiceNow demo instance and it worked correctly.
Hi Mark, did you call this from a UI action? Can you let me see how your UI action script in total is done. It doesn’t work in my case. We have an UI action called Cancel Change defined on change_request table
the scrip in there looks the following
current.state=4;
current.u_change_status=6;
current.update();
new Workflow().cancel(current);
g_form.addInfoMessage(“Workflows for ” + current.getDisplayValue() + ” have been cancelled”);
action.setRedirectURL(current);
both the workflow cancel part & the InfoMessage part doesn’t work
Yes, but my UI action only had the single workflow cancel line. I’m guessing that yours isn’t working because you’re calling your update first. Try moving ‘current.update’ after the workflow cancellation. If that still doesn’t work, then try the workflow cancellation on its own and see if you can get that to work.
Hi Mark, indeed the syntax works fine. The reason that it didn’t work in my case is that we had another client script that makes the a field mandatory, if I just fill that field & save it, the UI action is not really executed completely. If I would trigger the UI action again, then the WF is canceled
thanks for your help!!
Hi Mark,
The business rule is working for us as for as not initiating the next task in the flow is concerned. The problem I’m facing is that we have a Set Value box right after the cancellation point that is still being triggered. Do you have any suggestions on how to stop this?
My condition to cancel the workflow is state changes to Cancel. I’ve cancelled a change at a point where the following steps are
1) Set value to ZZZ
2) Create Task 123
Task 123 is not being triggered, which is exactly what I want. However, my state is being changed from Cancel to ZZZ, which is not what I want.
Any tips?
Only suggestion I can think of is to try adjusting the ‘Order’ field on your business rule. If you have a very high order it might be triggering after the workflow context is being executed. Try an order of 50 and if that doesn’t work you could try setting this up in a ‘before’ business rule.
Changing the order to 50 did the trick. Thanks Mark!!!
Awesome. I’m glad that worked!