Windows workflow is an excellent framework for implementing business processes. One thing that is missing in it is direct support for human activities. Although several approaches to solving this problem appear in Microsoft publication [1, 2], they are not generic enough for general usage. In this article we will define one of the approaches to a completely generic implementation of human activities in WF.
The complexities of supporting human interactions present multiple challenges. Some of them are:
These issues have been realized by the industry and resulted in two major specifications aimed to solve these problems [3, 4]. We will try to build our implementation following the spirit, not the letter of the specifications.
Main components of the overall solution are presented at Figure 1.
Figure 1 Solutions components
In the heart of the solution is a work queue manager. This is a centralized service keeping track of all tasks for all of the users of the system. Any workflow (or a service/application containing workflow), which requires a human activity, invokes a custom workflow activity [5], which submits the request to the work queue manager persisting them and allowing other components of the system to work with these requests. By doing this a work queue manager is becoming a decoupling layer between workflow engine and human activity execution, thus providing support for the cases where user is not present in the system during workflow execution. Also by being a centralized service a work queue manager allows to combine all of the tasks for a given user, regardless of the process that they have initiated from. Because different user tasks can require different input information and can produce different outputs, communications between workflow and human activity is XML in and XML out, which allows processing any possible request and response generically. Although usage of XML might seem as a complicating factor for the implementation, an excellent support for XML serialization, implemented in .Net [6] makes mapping between XML and objects a breeze. A work queue viewer is a GUI application allowing a user to see all of the tasks that are ready for his input. This application is generic, displaying only essential elements of a task, including, name, type, priority, creation, etc. Based on this information in the queue a user can decide to work on a particular task. The actual processing of the task is done by a task application, supporting functionality, specific for a given task. A Work Queue maintenance application provides a UI for administrative support of Work Queue manager. It allows viewing and modifying existing human task, viewing their history, etc. Finally a Human activity is a custom activity (see sidebar "Windows Workflow Foundation Component Model") implementing communications with the Task queue manager and presenting a very simple programming model for the human task execution to the workflow developer. From his point of view human interaction becomes no different than an ordinary service invocation.
The overall interaction of components is presented at sequence diagram (Figure 2)
Figure 2 Sequence Diagram
As we can see from the above the overall solution includes two types of components:
In this article we will describe only generic components of solution.
As we have defined above, a work queue manager is a centralized service. Its functionality is based on the data contracts, presented at Figure 3.
The major components of this data model are:
Figure 4 Task state transition diagram
When task is submitted to the work queue manager, it is in a ready state. Once it is requested by an application for an execution it transitions to a ready state. When an application completes task process, task moves to a completed state, which signals work queue manager to return response to a human activity about task completion. Alternatively if task processing returns cancel or times out, a task returns back to a ready state.In addition to the data types, data model defines Fault data types, presented at Figure 5.
A work queue manager exposes three groups of services - Workflow services, User services and Maintenance services.
Workflow service section (Figure 6) defines a service, which is used by a human task activity to submit a task for an execution, and an interface which has to be exposed by a workflow service and is used by a work queue manager to signal execution completion. These two services provide integration between human activity, running in a workflow and a work queue manager.
Figure 6 Workflow Services
Submit for execution service, implemented by a work queue manager, receives requests from human activities that can be part of many different workflows. Once the request is received, it is stored in a database for a further processing.
A completeExecution contract, although defined here, is implemented by a workflow. This service is used to signal workflow that an execution of a particular task is completed and a workflow can proceed.
User services (Figure 7) are implemented in support of user's interactions with a work queue manager. WorkWithItems service supports three operations:
Figure 7 User Services
Maintenance services (Figure 8) are implemented in support of work queue manager maintenance application.
Figure 8 Maintenance Services
View tasks method returns a list of existing task using a filter defined by MaintenanceQuery data type. After looking at the tasks, they can be modified and changes can be returned to the work queue manager using Update task method.
Service database design (Figure 9) Contains tables, necessary for persisting all of the information associated with the human task. The main table - Human task table contains all the basic human task information, including task name, ID (assigned by a service), priority and task life cycle events, supplemented by information about who and when have executed these events.
Figure 9 Work Queue Manger Database
Additional tables contain additional task information and include:
In order to optimize data access we have also implemented several stored procedures and a view. Stored procedures are:
AddTaskCallback
is a stored procedure for adding callback information and associating it with a given human task (using InsertTaskCallback
stored procedure, below). It first checks whether a given callback already exists and if it does, uses existing callback record, otherwise creating a new one in Callback
table. It then invokes an InsertTaskCallback
stored procedure to create a link. InsertTaskCallback
is a stored procedure populating TaskCallback
table, thus creating a relationship between a given callback and a human task. AddTaskType
is a stored procedure for adding task type information and associating it with a given human task (using InsertTaskTypeTask
stored procedure, below). It first checks whether a given task type already exists and if it does, uses existing task type record, otherwise creating a new one in TaskType
table. It then invokes an InsertTaskTypeTask
stored procedure to create a link. InsertTaskTypeTask
is a stored procedure populating TaskTaskType table, thus creating a relationship between a given task type and a human task. AddTaskPotentialOwner
is a stored procedure for adding potential owner information and associating it with a given human task (using InsertTaskPotentialUser
stored procedure, below). It first checks whether a given potential owner already exists and if it does, uses existing potential owner record, otherwise creating a new one in PotentialUser
table. It then invokes an InsertTaskPotentialUser
stored procedure to create a link. InsertTaskPotentialUser
is a stored procedure populating TaskPotentialUser
table, thus creating a relationship between a given potential owner and a human task. Usage of these stored procedures decreases the amount of database access by about a factor of 2 while minimizing the amount of database data by eliminating duplicates.
Database view (Figure 10) simplifies database accesses for reads. All of the task information (including task type) for a given user can be obtained from a single view.
Figure 10 Complete task view
A class diagram for the persistence layer, implementing repository pattern, is presented at Figure 11.
Figure 11 Persistence class Diagram
The overall implementation of the service is fairly straight forward. Once a particular method is invoked it delegates execution to the repository class (Figure 11), which implements all required database access.
A human activity is a custom workflow activity implementing human interaction. This activity hides communications with the work queue manager from a workflow designer and allows treating user interaction similar to an ordinary service invocation.
Implementation of this activity is based on workflow queues [7] providing asynchronous communication between activities and the outside world: activities register to receive messages on a queue and services send messages on queues. A custom activity can use this model both to handle external events as well as to communicate completion of asynchronous activity execution. This allows an activity to execute up to a point, and then wait for stimulus in order to continue execution. The overall interaction of such implementation is presented at Figure 12.
Figure 12 Activity implementation using Workflow Queue
Once started, activity execution will continue for as long as it can. Upon reaching activity point that requires external execution, the activity registers with a workflow queue. Then the workflow instance enters the waiting state and can be passivated (persisted). Once an external execution completes, it enqueues information into the queue. At this point a runtime reactivates a workflow instance, which continues execution.
The actual implementation of human activity consists of two parts - activity itself and a callback service.
A Human activity sends a message to the human task manager to start a new human task processing. If invocation of this service is successful, the activity registers itself to a workflow queue and goes into waiting state. If there are any errors, executing service, an activity throws a workflow fault that can be processed by a workflow.
When a reply is received by a service it enqueues the reply to the activity's work queue. A queue message wakes up an activity, which dequeues reply and finishes its execution.
A callback service implements complete execution contract (Figure 6) and has to be started by a service/application implementing workflow. In order for this service to work correctly, a WorkflowRuntime
has to be set on it. This can be done using a public static variable on a executionComplete
class.
A human activity needs several parameters for its execution - task type, priority, etc. These parameters are defined as DependencyProperty
[8]. DependencyProperty
can then be exposed to be set by workflow designer [9], thus allowing setting activity parameters visually with no programming (Figure 13).
Figure 13 Configuring Activity Parameters
A work queue viewer is implemented as a user control (Figure 14), which can be put on any form. This control implements a dataview control and takes a delegate as a parameter. When any cell of a given row is clicked, a delegate is invoked with a task ID and task type. Figure 14 shows a simple delegate that just pops up a message box.
Figure 14 Work Queue Viewer
Despite the push for complete automation of the business processes, human activities still play, and will continue to play an important role in business process implementations. As we have defined in the beginning of the article introduction of user interactions brings a lot of additional concerns, that are not directly related to workflow implementation. Completely decoupled implementation, described in this article, allows for separation of concerns between workflow development and user interaction development. Additionally, centralization of the human tasks support in the human task manager simplifies an aggregation of task management for a given user.
From:http://www.infoq.com/articles/lublinksy-workqueue-mgr