Tuesday, March 24, 2009

Breaking The Workflow Mobious Loop

I'd built a WF on a list that fires when an item is created or changed only. It would check a field to see if it matches a RegularExpression- If so, set a Yes/No field in the current item to Yes. Otherwise, set it to No. That's it.

The regular expression (An artform in, and of, itself, which I'm convinced has something to do with alchemy or witchcraft) was fine but the WF locked up the item for an indeterminate amount of time so you can't go back into that item to make other changes. Attempting to do so resulted in the following error-


Save Conflict: Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Microsoft.SharePoint.SPException: Save ConflictYour changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.
Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace: [SPException: Save ConflictYour changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.] Microsoft.SharePoint.WebControls.SaveButton.SaveItem(SPContext itemContext, Boolean uploadMode, String checkInComment) +452 Microsoft.SharePoint.WebControls.SaveButton.SaveItem() +58 Microsoft.SharePoint.WebControls.SaveButton.OnBubbleEvent(Object source, EventArgs e) +249 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +35 System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) +115 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +163 System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +174 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102



Even AFTER the workflow shows "Completed" Even AFTER 15 minutes of doing nothing. No one else was working on the list. No other workflows were involved.

After lots of WF analysis, a few beers, and some therapy, I'd concluded that the SPD WF is getting stuck in a loop. It shouldn't, but it is.

This only seems to happen if the WF is launched automatically whenever an item is changed AND that WF is modifying a field in the current item. Here's the scenario

You update an item.The WF kicks off and updates a field in the current item,
  which then registers as the item being changed...
    which kicks off the WF again...
      which updates the field in the current item...
        which registers as the item being changed...
          which kicks off the WF again...

See where I'm goin' with this?

I've experimented with a number work arounds and the best one I've found involves just adding a few Actions to your WF step.


  • After you: "Set field in current item"

  • Add to the same step: "Wait for field change in current item"

  • Then add to the same step: "Stop Workflow"


  • Stopping the workflow once the field is updated is crucial.

    I've also found that adding "Log to history list" at varying points in the WF step helps in debugging issues. Particularly if need to see if your WF Conditions are being met.

    I hope this helps save soemeone else some time. Though, I still encourage a few beers and some therapy.

    Cheers!

    No comments: