Click here to Skip to main content
Click here to Skip to main content

Retry Activity Execution in Sequential WWF

, 24 Mar 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Knowledge sharing article on WWF.

Introduction

This article I am writing for those who already knows developing in WWF (Sequential Workflow), Here I am going to provide the solution on how to execute same activity within a Sequential Workflow if there is uncertain failure. Why I came to this solution because, I am seeing this problem since long time within my project, and every time manual work was required to complete the Orchestration of the workflow.

Background

If your workflow has many sets of activities which calls external/internal Web Services/WCF and due to internal server error in those web services/wcf it was raising FaultException (WebException) and your Workflow Activity was failing/terminiting due to it, eventually your whole workflow was terminiting due to that. Because this is how you have developed/designed your workflow to stop there itself if there's any issue in an activity. But there are some certain senario's where you don't want the compelete workflow to stop and you may require that set of activity again execute itself to limited number of time to see if it works or not (Replay of same request to web service), and if that works, it should execute rest other activities in the workflow without terminiting the workflow.

Understanding states of customer Activity

There are six states an activity can be in during its lifetime. These states are Initialized, Executing, Canceling, Closed, Compensating, and Faulting

During the Initialized state, an ActivityExecutionContext has been created for the activity and other initiation details specific to that activity have been executed. When an activity enters the Executing state, the primary functionality of that activity is performed. An activity is put into the Canceling state by a parent activity explicitly, or because an exception was thrown during the execution of that activity.  The Closed state is the last and final state of an activity. The one caveat to this is if an activity successfully completes, but then must go through the Compensating state based on business logic. The activity will then transition from Closed to Compensating and then back to Closed once the compensation logic has completed.  

The following flowchart shows how an activity transitions between the various activity states.

So basically on a happy path a activity go through  Initialized, Executing and Closed. 

Point of research 

We know if an exception is thrown during the Executing state, Canceling state, or Compensating state of an activity, it will transition to the Faulting state.

 Note: An activity cannot move from the Closed state to the Executing state.  

Since we know once activity get closed it can not be moved to Executing state, but we can re-execute the activity before it close. Which mean that if for any reason activity get into Faulting State, it possible to move back it to Executing state. 

Now, we know there is new transition can be possible here. Below image show new state transition in green line. 

As we know each state of activity can be control by its predefined methods. Which we can override in our customer activity. Below are the two main override methods which i am going to use for my research.  

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)

How to get activity state to Executing from Faulting State? 

We can achieve this by handling Fault inside the Activity. By overriding Activity state using HandleFault method we can know what is exectionContext and which type of exception raised and to re-execute the activity we can call Execute Method which by passing exectionContext in it. But we have to be very careful in doing this and we should make sure we are handling the replay properly with some logic, because it may takes you to deadlock condition if you don't do it.

Using the code  

Here, I am going to show you using my sample POC project, how did i achieved it and you can also use same approach to achieve it. Only thing which will differ for you; is that your logic/requirement of replay.  We always  need to make sure about the replay logic which should not go into endless loop. 

Below is my project solution.

 

And in this I have below Sequential workflow, having three activities.  

 

In CallWebServices activity i am trying to simulate this activity is calling web service and it may get Server Error which will raised server error fault exception, resulting complete workflow will terminating due to exception raised by it.  

Now, to solve the problem of complete workflow termination and again re-try of executing same activity again from there itself so that if next re-try works and it gets success response from web service, the workflow should continue to complete the orchestration.  

Replaying => I am trying to achieve moving the activity state from Faulting to Executing  

To achieve to the solution of this problem, I have added a BaseActivity which will be inherit in all of my workflow activities, like below. 

public partial class Activity1: MyBaseActivity 

Why I have though to write base activity because as per our requirement for the solution, we require each activity should have this feature for replaying. 

Also I have added a dependency property to my base activity to set/limit the replay count. So if any activity inheriting my base activity should set this property. Here in below pic i have set AllowedReplayCount to my CallWebServices Activity as 2, which means this activity can re-play it self to max 2 times.

  

Below is code to add Dependency Property to my base activity 

public static DependencyProperty AllowedReplayCountProperty = 
  DependencyProperty.Register("AllowedReplayCount", typeof(Int32), typeof(MyBaseActivity));

[DescriptionAttribute("AllowedReplayCount")]
[CategoryAttribute("Replay Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public Int32 AllowedReplayCount
{
    get
    {
        return ((Int32)(base.GetValue(MyBaseActivity.AllowedReplayCountProperty)));
    }
    set
    {
        base.SetValue(MyBaseActivity.AllowedReplayCountProperty, value);
    }
}

In this base activity I am handling the Fault raised by the activity by overriding the HandleFault function. This function gives us two important data; executionContext and execption. Using these data I have applied my logic of re-executing same activity. And using dependency property I will be controlling the re-play will make sure it does not fallows into endless loop. 

protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
{
    if (exception is WebException && ReplayCount < AllowedReplayCount)
    {
        if (!exception.Message.Contains("404") || !exception.Message.Contains("409"))
        {
            Console.WriteLine("Faulted " + executionContext.Activity.Name);
            ReplayCount++;
            return Execute(executionContext);
        }
    }
    return base.HandleFault(executionContext, exception);
}  

Till now we see how to re-play the same activity by doing HandleFault function, but this is not it, we also require workflow to execute rest other activity after replay success for faulted activity. We require this because its basic feature of workflow; if any activity fault it terminate the complete workflow.  So we have to stop Workflow to move into Faulting State from Executing State. 

To achieve this situation, I have added faultHandlerAcitivity inside my base activity 

 

And to support the replay, I have set the FaultType as System.Net.WebException for faultHandlerActivity. Also I have added codeActivity

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    CodeActivity senderActity = sender as CodeActivity;
    FaultHandlerActivity faultException = senderActity.Parent as FaultHandlerActivity;
    if (faultException.Fault is WebException)
    {
        if (ReplayCount > AllowedReplayCount)
        {
            throw faultException.Fault;
        }
    }
    else
    {
        throw faultException.Fault;
    }
}

I am using codeAcitivity to check if fault raised by activity fallow under replay condition or not. If its not part o my replay condition then only I am allowing it to raise the fault to workflow.  

That's all required to have this replay activity feature in a workflow. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

SumitJaiswal
Software Developer (Senior) Tata Consultancy Services
India India
MCTS in Windows Workflow foundation 3.5

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web03 | 2.8.141015.1 | Last Updated 24 Mar 2013
Article Copyright 2013 by SumitJaiswal
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid