Canceling executing workflows on task closure

/, Graphical workflow/Canceling executing workflows on task closure

Canceling executing workflows on task closure

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

Cancel Workflow Business Rule
Name: Cancel workflows
When: After
Insert: True
Update: True
Condition: current.active.changesTo(false)
Script:

//Query for all executing workflows and cancel any running activities
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.

//Query for all executing workflow contexts
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);
}
}

About the Author:

22 Comments

  1. alli December 29, 2009 at 12:25 am - Reply

    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!

  2. Mark Stanger January 4, 2010 at 12:03 pm - Reply

    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.

  3. jointheclub April 23, 2010 at 9:53 am - Reply

    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.

    • Mark Stanger April 23, 2010 at 10:06 am - Reply

      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.

  4. alli May 3, 2010 at 8:36 pm - Reply

    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

    • Arun June 24, 2010 at 11:31 pm - Reply

      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

      • Mark Stanger June 25, 2010 at 6:12 am - Reply

        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.

  5. Bill Collins October 26, 2012 at 5:35 pm - Reply

    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.

  6. ND November 1, 2012 at 8:03 pm - Reply

    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

    • Mark Stanger November 2, 2012 at 5:52 am - Reply

      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.

      • ND November 2, 2012 at 8:25 am - Reply

        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

        • Mark Stanger November 2, 2012 at 9:52 am - Reply

          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.

  7. ND November 2, 2012 at 10:56 am - Reply

    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.

  8. Shuguang Shi December 11, 2012 at 5:19 am - Reply

    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

    • Mark Stanger December 11, 2012 at 5:24 am - Reply

      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.

      • Shuguang Shi December 13, 2012 at 4:09 am - Reply

        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

        • Mark Stanger December 13, 2012 at 5:42 am - Reply

          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.

          • Shuguang Shi December 14, 2012 at 4:25 am - Reply

            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!!

  9. Thrishna Strachan-Visser March 17, 2017 at 7:47 am - Reply

    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?

    • Mark Stanger March 17, 2017 at 9:02 am - Reply

      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.

      • Thrishna Strachan-Visser March 28, 2017 at 5:20 am - Reply

        Changing the order to 50 did the trick. Thanks Mark!!!

Leave A Comment