This blog post is a contribution from Andy Li, an Escalation Engineer with the SharePoint Developer Support team.
Andy is one of the Escalation Engineer with the SharePoint Developer Support team. The series of posts on Workflows are his contribution for the community to better understand the internals of workflow runtime and how it interacts with SharePoint.
Jump to the next parts in this series.
SharePoint Integration with Workflow Runtime
The following diagram talks about the high level components of SharePoint workflow. Let me first explain some high level data flow and then I’ll talk about each component in more detail in the next few sections.
First think about how you start a workflow. This part maps to the left side of the chart where the blue arrows go:
1. First you go to the workflow page from the list or document library, click on the workflow association that you have setup with the list or document library. You will then be redirected to the Workflow Initiation form if you have a workflow initiation form setup for the association.
2. After you submit on the Initiation Form, the data flows to the SPWorkflowManager which is the only object in SharePoint object model that you can use to start a workflow instance.
3. SPWorkflowManager then tells the SharePoint workflow runtime object (SPWinOeHostService) that a workflow instance needs to be started.
4. The function of SPWinOeHostService is to talk to the Windows Workflow Runtime to actually kick off the workflow instance. It does this by calling System.Workflow.WorkflowRuntime.CreateWorkflow() and then call System.Workflow.WorkflowInstance.Start().
Another common scenario is submitting a workflow task, lot of people have difficulties understanding how the task data gets delivered to the workflow instance. This is actually the most complicated part of SharePoint workflow as it involves a lot of components on both Workflow runtime and SharePoint sides. I’ll explain the high level data flow first and a lot more details will be covered in the next few posts.
1. The process starts when you go to the Task list and open the task form for a workflow task.
2. If you have a custom task form, you will typically use SPWorkflowTask.AlterTask() to submit the change on the task, this API eventually calls the SPListItem.Update() to commit the change on the task. If you don’t have a custom task form, the OOB SharePoint task for does the same thing essentially.
3. The mechanism that enables the data flowing from the task to workflow is the event receivers. You might have already thought so. Yes that is the way the task data gets delivered to workflow. We’ll explain how the event receivers are registered on the tasks. For now you just need to know that each workflow task has an event receiver hooked with it. Its sole purpose is to route the change on the task to the corresponding workflow instance.
4. The event receiver calls SPWorkflowManager which again is the only way that you have to go through to get to the workflow runtime. This time it calls the non-public method SPWorkflowManager.RunWorkflow(). This also means that for a developer you’ll have to either call SPWorkflowTask.AlterTask() or SPListItem.Update() on a particular task or list item to trigger the workflow action.
NOTE: Notice that SharePoint 2010 introduced a new concept called Pluggable Service which enables workflow to talk to any external services, such as custom WCF service, etc. This is not possible in SharePoint 2007 where the only way to communicate with workflow is through SharePoint tasks. In this diagram the objects SPWorkflowExternalDataExchangeService is used for deliver custom event to workflow. It’s essentially the same with how a task change gets delivered to workflow so we’ll be using the built-in tasks to explain how everything works.
5. Next SPWorkflowManager will pass the data to SharePoint workflow runtime and it’ll try to figure out where the data should go. For example, whether this is a task or a regular item. Based on the type of the data it’ll call the corresponding the data exchange service to continue deliver the data.
6. All data exchange services are based on Workflow Communication Services. In SharePoint, Microsoft.SharePoint.Workflow.ITaskService is the interface that facilitates the data exchange between the workflow and SharePoint. We’ll talk more about this later in this guide.
Host Service: SPWinOeHostService
The Workflow Host service in SharePoint is the class SPWinOeHostService. Here is what it does:
- Instantiate System.Workflow.Runtime.WorkflowRuntime object.
- Plug the runtime services to workflow runtime:
* Persistence Service
* Subscription Service
* CommitWorkBatch service
- Communicate with workflow instance through Communication Services class:
* Your custom data exchange service based on SPWorkflowExternalDataExchangeService
- Handling WorkflowRuntime events, such as WorkflowStarted, WorkflowStopped events.
SharePoint uses SPWorkflow object to represent the underlying workflow instance on workflow runtime. This object contains the properties such as the workflow instance ID (System.Workflow.Runtime.WorkflowInstance), the associated SharePoint Web, List, ListItem of the Workflow instance and the other related information such as the history list, task list etc.,
Durability is a key feature of Windows Workflow Foundation, it means that workflows can be unloaded from memory while waiting for input and serialized into a persistent store, such as a SQL database or XML file. Whenever the input is received, the workflow runtime engine loads the workflow state information back into memory and continues the execution of the workflow.
When certain conditions happen while a workflow is running the workflow runtime engine will use a persistence service, if on is loaded in the runtime, to persist state information about the workflow instance. These conditions include such things as the following:
- When atomic transactions in TransactionScopeActivity activities and CompensatableTransactionScopeActivity activities are completed.
- When a workflow instance becomes idle and the UnloadOnIdle flag is set to true for a WorkflowPersistenceService. This occurs, for example, when you use a DelayActivity activity.
- When the runtime host application calls System.Workflow.Runtime.WorkflowInstance.Unload or System.Workflow.Runtime.WorkflowInstance.TryUnload on the workflow instance.
- When a workflow instance is terminated or complete.
- When a custom activity using the PersistOnCloseAttribute attribute completes.
If one of these conditions is met and a persistence service is added to the runtime engine, the runtime engine calls methods that are supplied by the persistence service to save state information about the workflow instance. Similarly, when the workflow runtime engine has to restore a previously persisted workflow instance, it calls methods that are supplied by the persistence service to load the workflow state information from whatever it was stored previously. In other words, the workflow runtime engine determines when persistence should occur, but it is up to a persistence service to perform the necessary persistence operations.
SharePoint extends the runtime Persistence Service, which is known as Dehyderation/Rehydration process. This service is defined in SPWinOePersistenceService class, and is plugged into the workflow runtime by SPWinOeHostService.
The main function of SPWinOePersistenceService is to persist workflow instance into SharePoint content database and load workflow instance from content database. Workflow runtime automatically determines the Persistence Point and call persistence service to unload the workflow instance.
The following screenshot shows the result when you run the following query on the SharePoint Content Database. The InstanceData is the serialized binary data of the workflow instance and the InstanceDataSize is the size of the workflow instance.
SPWinOESubscriptionService inherits from runtime WorkflowSubscriptionService. Developers can use subscription service to subscribe to workflow events and handle custom logic on the events, for example if you have an OnTaskChanged activity in your workflow, workflow runtime will call SPWinOESubscriptionService.CreateSubscription() method when it executes this activity. Runtime calls the subscription service to send a notification that an event has occurred and see if it needs to take any action.
Previously we mentioned that each workflow task has an event receiver associated with it and we didn’t explain where the event receiver come from, here is the answer:
The purpose of SPWinOESubscriptionService is to register an event receiver on the task list for each workflow task. The event receiver is responsible for handling ItemUpdated event on the task item, convert it into a workflow event and deliver it back to the workflow runtime. When the event reaches the workflow instance, the OnTaskChanged activity gets called. After the OnTaskChanged activity is finished, workflow runtime calls SPWinOESubscriptionService.DeleteSubscription() to remove the event receiver from the task.
The following table lists all the events that are handled by SPWinOESubscriptionService.
Let’s take an example, if you have two activities in your workflow code, for example OnTaskChanged activity and OnTaskDeleted activity, SPWinOESubscriptionService will register two separate event receivers on the task list, and each handles the ItemUpdated and ItemDeleted events respectively for the item.
SharePoint re-uses the DefaultWorkflowCommitWorkBatchService from Workflow Foundation. The purpose of this service is to enable custom logic for the commitment of work batches (also known as persistence points). When a work batch is committed, the workflow runtime calls into this service and gives it a delegate to do the actual commitment of the work batch. In SharePoint, all the task related updates use this service. For example, CreateTask activity is used to create a task item on the tasks list, but the task item is not committed immediately after this activity is done, instead this activity only prepares the properties for the new task then it sends the WorkBatch service a delegate to commit the task item into database. This also explains that if you try to get hold of the task item in a CodeActivity right after the CreateTask activity you will get an exception that the list item does not exist.
SharePoint provides several out of the box communication service to work with SharePoint objects. The table below explains the service interface and the service classes used in SharePoint:
|Service Interface||Service Class|
|ITaskService||SPWinOeTaskService implements the ITaskService, it is used to perform task related activities, such as task creation, deletion. It also responds to task related events, such as task created, task updated events.|
|SPWinOeWSSService implements both IListItemService and ISharePointService. It provides workflow runtime the ability to perform item related operations and respond to item related events. It also implements ISharePointService, which can be used to do something like sending email, logging event into History list.|
|IWorkflowModificationService||SPWinOeWSSService also implements the IWorkflowModificationService interface to enable the capability of workflow modification.|
SPWorkflowManager is the only object that developers can use to interact with the SharePoint workflow runtime. The primary functions of this object includes:
1. Allow developers to start SharePoint workflow from custom applications.
2. Communicate with SharePoint workflow runtime (SPWinOeHostService) to deliver external events to workflow.
In the next part of this post, we’ll discuss about Workflow Event Processing Pipeline in detail.