Service Pack 2 prevents an on-change workflow from starting itself

Hello all, Stephen here again — I’m a writer for SharePoint Designer. I’d like to tell you about a fix that was included in Service Pack 2 for Office SharePoint Server 2007 and Windows SharePoint Services 3.0. This fix affects workflows designed in SharePoint Designer 2007. Then I’ll show you how to intentionally create a workflow loop by using two workflows instead of one.

Before Service Pack 2, it was too easy to inadvertently design a workflow that triggered itself and created an infinite loop. For example, consider this scenario:

1) A workflow starts when an item is changed.

2) The workflow updates (or changes) the current item (e.g. by using the Set Field in Current Item action).

3) Because the workflow changes the item, it triggers itself.

So if you had an on-change workflow that sends you an e-mail and then updates the current item, you could quickly receive several hundred e-mails in your Inbox.

After you install Service Pack 2 on your server, it is no longer possible for a workflow that starts when an item is changed to trigger itself by changing/updating the current item. This infinite-looping scenario is not possible:

clip_image002

Many people, however, have designed workflows that actually leverage infinite looping. For example, you could design an on-change workflow that loops endlessly on a task item and that sends a daily reminder until that task is marked complete. The workflow triggers itself by updating a Counter column that was added to the list just for this purpose. And the workflow has a rule that stops or “short circuits” the workflow if some condition is satisfied — in this case, the workflow stops without changing the current item if the task Status = Completed. After SP2, this workflow will in effect be broken because it cannot trigger itself.

SP2 does not block infinite loops, which can be useful, but to re-create what worked before you must design two (or more) on-change workflows that trigger each other. Two on-change workflows that trigger each other by updating/changing the current item is a “co-recursion” scenario:

clip_image004

In addition, it is very common to implement a state-based workflow by using several shorter workflows that trigger each other. For example, you might have a list with a Status field and several on-change workflows attached to that list. All of those workflows include a step at the end that updates the Status field. So one workflow triggers several others by updating the Status, and then those workflows look at the value in the Status field to determine whether they should continue running or stop. This state-based workflow is also a “co-recursion” scenario because one workflow starts many other on-change workflows by changing/updating the current item. Service Pack 2 does not block this type of state-based workflow that relies on co-recursion.

Recap

· Before SP2, a single on-change workflow could enter an infinite loop by updating the current item, thus triggering itself.

· After SP2, an on-change workflow can trigger any other on-change workflows by updating the current item, but an on-change workflow cannot trigger itself. So co-recursion scenarios -- including any scenario that implements a state-based workflow by using many smaller on-change workflows -- are not blocked.

· As a reminder, it has never been possible to create an infinite loop by having an on-create workflow create an item in the current list. Every workflow has a property that contains the “workflows I cannot start” — this property is used to prevent looping for workflows that start when an item is created.

· As a further reminder, all of the previous scenarios involve only workflows attached to a single list or library. Infinite looping in cross-list scenarios has never been blocked for either on-change or on-create workflows.

Creating loops before Service Pack 2

This section presents an example of how a single on-change workflow could leverage infinite looping before SP2. After SP2, this workflow will not trigger itself, so the next section presents an example of how to create a loop by using two separate workflows.

Assume you have a task list named Team Tasks, and you want to design a workflow that will send a reminder every day until the task is marked complete.

First, add a column named Counter to the list with a default value of 0.

clip_image006

You need to hide the Counter columns from the list forms (New Item, Edit Item) so that only the workflow can access/update it. Fist, on the list settings page, click Advanced Settings, and then allow the management of content types.

clip_image008

On the list settings page, click each content type, and on the next page click the Counter column. Make the Counter column hidden. Do this for every content type in the list.

clip_image010

After creating and hiding the Counter column so that it does not appear in forms, you’re ready to design the workflow.

The Daily Reminder workflow should start whenever an item is created or changed.

clip_image012

The first step checks for two things: (1) If the task has already been marked complete, the workflow stops. This rule “short-circuits” the loop whenever the task is finally marked complete. (2) If the task is not completed, the workflow checks to see if the due date is in the future (greater than today). If this is true, the workflow pauses until the due date, because you don’t want to send reminders until the due date has been reached.

clip_image014

The second steps again checks whether the task is completed (in case the workflow paused until a due date on the previous step, and the task was completed in the interim). If the task is still not complete, the workflow pauses for one day.

clip_image016

The third step again checks to see if the task was completed while the workflow was paused; if true, the workflow stops.

If the task has not been completed, the workflow (1) sends the e-mail reminder; (2) set the CurrentCount variable by doing a lookup to the Current Item/Counter field; (3) adds 1 to CurrentCount and stores this value in a NewCount variable; and (4) sets the Counter column to the value stored in the NewCount variable.

Basically, this step increments the Counter column by 1 each time the workflow runs, so you can look at the Counter column to see how many reminders have been sent. And most importantly, the “Set Field in Current Item” action at the end of this step is what “changes” the current item, thus causing the workflow to trigger itself and create the loop.

clip_image018

Creating loops after Service Pack 2

After SP2, you can still achieve this looping effect, but it requires designing two workflows that trigger each other (co-recursion) instead of a single workflow that triggers itself.

Here you’ll use a (1) Counter workflow that increments the count and a (2) Worker workflow that actually sends the reminder mail.

1st workflow — the Counter workflow

As above, you need to create a Counter column in the list with a default value of 0, allow the management of content types, and make this field hidden for every content type in the list.

clip_image006[1]

This two-workflow design requires a second column, SendMail, which will act as a flag for the Worker workflow. The default value must be No – otherwise, any change to a task item would cause the reminder mail to be sent.

clip_image020

The Counter workflow will start when an item is created or changed.

clip_image022

The first step checks the task status – if the task is complete, the Counter workflow stops.

clip_image024

If the task due date is in the future (greater than today), the second step pauses until the due date, because you don’t want to send reminders until after the task is due.

clip_image026

The third step again checks for task completion, in case the task was completed while the workflow was paused on the previous step. If the task is still not complete, the workflow pauses for one day.

clip_image028

The final step checks the status again to see if the task was completed during the previous day-long pause. If not, the workflow updates the current item by (1) incrementing the value of the Counter column by one and (2) setting the SendMail flag to Yes (the default value is No).

clip_image030

2nd workflow — the Worker workflow

The Counter workflow above ends by updating (changing) the current item. These updates trigger the Worker workflow, which is set to start when an item is changed.

clip_image032

The Worker workflow simply checks to see if the SendMail flag is set to Yes; if true, the workflow sends the reminder message and sets the flag back to No.

Setting the SendMail flag to No is the change that triggers the Counter workflow above. The Counter and Worker workflows will trigger each other, sending daily reminders until the task is marked complete.

clip_image034

Alternatively, instead of an infinite loop, you can have the Worker workflow escalate the task notification when the Counter column reaches a certain value — say 5 reminders. The following step executes different branches depending on the reminder count. When the count reaches 5, the workflow sends a message to a manager, whose e-mail address you can either “hard-code” into the Send an Email action or retrieve from a list by using a workflow lookup.

clip_image036

You could also have the Worker workflow reassign the task to a different individual or group after a certain number of reminders have been sent. For this step, the workflow reassigns the task to a SharePoint group comprised of team members who are responsible for following up on such escalated tasks.

clip_image038

If you want to end the loop when the count reaches a certain number, also make sure to add a branch to the first step of the Counter workflow – not the Worker workflow. This branch stops the loop when the Counter column reaches 6.

clip_image040

I hope you find this useful.

—Stephen