Farhan's Two Cents on Collaboration, Integration & Enterprise Tech.

Farhan Khan

  Home  |   Contact  |   Syndication    |   Login
  29 Posts | 0 Stories | 51 Comments | 50 Trackbacks

News

Archives

EAI Folks

EAI Standards

EAI Tools

iPhone

Relativity

UnCategorized

Tuesday, November 08, 2005 #

The example here builds a sample workflow which is event driven. The test harness will emulate a Document arrival notification and send notification to the workflow. Upon receipt of the event the workflow shall come out of its latent state and become active. The workflow will then check if the passed in data is for urgent processing (based on Priority parameter passed) and process it accordingly. The code has been kept very simple with fictitious processing times e.g. making thread sleep longer for normal processing etc.

The emphasis is on how to invoke the workflow, pass parameters and utilize some basic activities within the WF development environment.

First off, the development environment includes the following:

  • Windows Server 2003 with SP1
  • Visual Studio Final Release
  • Windows Workflow Foundation - Visual Studio Extensions [published in Nov’05]

 

  1. Select New Project >Sequential Workflow Console Application (Under C#>Workflow)
  2. Since an Event Driven workflow is desired, we have to first of all define an interface and events that the event sinks can listen to. Below is the code for a simple notification service and events for the event sink to hook upto. You can find description of the assemblies, attributes, keywords defined in the code below @ http://winfx.msdn.microsoft.com/.

using System;

using System.Workflow.ComponentModel;

using System.Workflow.Runtime;

using System.Workflow.Runtime.Messaging;

 

[DataExchangeService]

public interface INotificationService

{

    event EventHandler<NotificationEventArgs> NotificationAArrived;

    event EventHandler<NotificationEventArgs> NotificationBArrived;

}

 

[Serializable]

public class NotificationEventArgs : WorkflowMessageEventArgs

{

    private string notificationId;

 

    public NotificationEventArgs(Guid instanceId, string notifId)

        : base(instanceId)

    {

        notificationId = notifId;

    }

 

    public string NotificationId

    {

        get { return notificationId; }

        set { notificationId = value; }

    }

}

 

public class NotificationService : INotificationService

{

    public NotificationService()

    {    }

 

    public void RaiseNotificationAArrivedEvent(string notifId, Guid instanceId)

    {

        if (NotificationAArrived != null)

            NotificationAArrived(null, new NotificationEventArgs(instanceId, notifId));

    }

 

    public void RaiseNotificationBArrivedEvent(string notifId, Guid instanceId)

    {

        if (NotificationBArrived != null)

            NotificationBArrived(null, new NotificationEventArgs(instanceId, notifId));

    }

 

    public event EventHandler<NotificationEventArgs> NotificationAArrived;

    public event EventHandler<NotificationEventArgs> NotificationBArrived;

}

 

  1. Let us add some parameters to the workflow that have to be passed to the workflow before any processing can begin. By clicking on Workflow background and then looking at the properties (Parameters) will lead you to the Parameters dialog. Define three parameters Priority (In), Data (In) & Status (Out), all of type System.String.

  1. There is one more step involved in order to access these parameters in the workflow. They need to be declared as public properties in the <workflow>.designer.cs  file. By doing so these properties shall be accessible in configuration windows of different activities where applicable e.g IfElse Activity etc.

public string Priority

{

      get { return (string) Parameters["Priority"].Value; }

      set { Parameters["Priority"].Value = value; }

}

 

public string Data

{

      get { return (string) Parameters["Data"].Value; }

      set { Parameters["Data"].Value = value; }

}

 

public string Status

{

      get { return (string) Parameters["Status"].Value; }

      set { Parameters["Status"].Value = value; }

}


 

  1. Next lets introduce a decision making step by adding an If-Else activity. In the properties of the activity, define condition of type ‘System.Workflow.Activities.Rules.RuleConditionReference’. Since we exposed the parameters as public properties in the last step we can access them in the scoped member drop down in the condition expression dialog. You can add a condition which checks the Priority parameter for equality against string ‘High’.

  1. Next step is to add some processing inside the If logic. Add a simple code activity and some simple code by double clicking it. (you can invoke any methods given that the assembly is referenced properly)

private void code1_ExecuteCode(object sender, EventArgs e)

{

   //this.Status = SampleUtils.DoSomeWork(10);

     this.Status += "(Priority Processing)";

}

 

  1. Invocation of the workflow comprises of numerous steps. The code itself is pretty descriptive (I used a Windows Form application to invoke the workflow). 

static AutoResetEvent waitHandle = new AutoResetEvent(false);

IASequentialSample.NotificationService notifService = null;

WorkflowRuntime runtime = null;

StringBuilder sb = null;

 

private void button1_Click(object sender, EventArgs e)

{

    StartWorkflowRuntime();

 

    Guid instanceID = Guid.NewGuid();

 

    Assembly asm = Assembly.Load("IASequentialSample");

    Type workflowType = asm.GetType("IASequentialSample.Workflow1");

           

    Dictionary<string, object> parameters = new Dictionary<string, object>();

    parameters.Add("Priority", textBox1.Text);

    parameters.Add("Data", "Some Data");

 

    WorkflowInstance ins  = runtime.StartWorkflow(workflowType, parameters);

 

    notifService.RaiseNotificationAArrivedEvent("someId", ins.InstanceId);

 

    waitHandle.WaitOne();

    runtime.StopRuntime();

 

    textBox1.Text = sb.ToString();

}

 

private void StartWorkflowRuntime()

{

    runtime = new WorkflowRuntime();

 

    sb = new StringBuilder();

 

    // Register event handlers for the WorkflowRuntime object

    runtime.WorkflowTerminated += new

                   EventHandler<WorkflowTerminatedEventArgs>(WorkflowRuntime_WorkflowTerminated);

    runtime.WorkflowCompleted += new

                   EventHandler<WorkflowCompletedEventArgs>(WorkflowRuntime_WorkflowCompleted);

 

    // Add a new instance of the Notification Service to the runtime

    notifService = new IASequentialSample.NotificationService();

    runtime.AddService(notifService);

 

    // Start the workflow runtime

    runtime.StartRuntime();        

}

 

public void WorkflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)

{    sb.Append("Workflow Runtime terminated");  }

 

public void WorkflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)

{

    sb.Append("Workflow Runtime Completed; Status Returned = " + e.OutputParameters["Status"]);

    waitHandle.Set();

}

 

The workflows that are not event driven are even simpler to run by simply starting and stopping the workflow through the WorkflowRuntime.

You may try out other activities or code your own however above account will do the basic plumbing for you to get an event driven workflow running.


If you are interested in a developing a State machine workflow there are already many references/tutorials out on the web.

In particular, I found the following very helpful while understanding the concepts:

http://blogs.msdn.com/federaldev/archive/2005/10/27/485691.aspx (Hello world)

 

http://channel9.msdn.com/Showpost.aspx?postid=122931

 

http://www.masteringbiztalk.com/blogs/jon/PermaLink,guid,7ec8a0d3-7c96-405f-aa60-edb23ce06d3b.aspx

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati