This project is read-only.

Orders Managers Documentation

Contents

Objective

Build an application that demonstrates how to integrate the Composite UI Application Block (CAB) and the Smart Client Software Factory (SC-SF) with Windows Workflow Foundation.

Conceptual solution

Order Manager is a CAB-based application that extends the user interface of the sample application "StateMachine” shipped with the Windows Workflow Foundation SDK.
The solution allows users to create orders and process them following a defined workflow. The solution also demonstrates how to query the state of the orders.
ConceptualSolution.png

Logical solution

LogicalSolution.png

Smart Client Application’s User Interface

The application contains a Shell form composed of the following elements:
  • An OutlookBarWorkspace on the left. This workspace displays three lists of orders:
    • Opened Orders
    • Processed Orders
    • Shipped Orders
Each list is displayed within a different view in the workspace.
  • A DockPanelWorkspace in the right: This workspace shows two different types of views:
    • The view is used to create a new order.
    • The view shows the details of a selected order and allows changing the state of the order.
SmartClientApplicationsUserInterface.png

Use cases

Creating a new order

The OrderView view allows a user to fill data of an order using the Save button; the OrderViewPresenter uses OrderService to persist the order in a repository and to update the Workflow.

Sequence

CreatingANewOrder.png

Editing an order

When selecting an order in the LeftWorkspace a new OrderView is created and showed in the RightWorkspace. This view is loaded in the “edit state” (when loading the view, it is configured to edit the order) and the order information is shown.

Sequence

EditingAnOrder.png

Listing the orders by state

Each view inside the LeftWorkspace uses an IOrderPollingService implementation that creates a new thread to request periodically the orders by state to the OrderService.
For example the Opened Orders View calls this service to get the opened orders and show them.

Sequence

ListingTheOrdersByState.png

Workflow Project

It is a “State Machine Workflow” that represents the states of an order. These states are:
  • Opened
  • Processed
  • Shipped
  • Cancelled
WorkflowProject.png
This workflow is managed through an ExternalDataExchangeService that communicates the workflow with the SCSF application.

Services

OrderService

This service relies on two other services:
  • OrderWorkflowManager: Communicates with the Workflow to manage the orders state.
  • OrderRepository: Store orders data.

Methods

  • SaveOrder. This method saves an order in a specified repository. If the order exists in the repository it updates the order. If the order does not exist, the new order is inserted into the repository. It also uses OrderWorkflowManager service to create or update a workflow instance for an order. For example: Changing the state of an order from Opened to Processed (see NotifyOrderProcessed method of OrderWorkflowManagerService).
  • GetById. This method gets a specified order from the repository.
  • GetByState. This method use OrderWorkflowManager to get all Orders in a given state and then gets these orders from the repository. For example this method can get all the Shipped Orders.
  • ShipOrder. This method use OrderWorkflowManager service to send an OrderShipped event to the Workflow.
  • ProcessOrder. This method use OrderWorkflowManager service to send an OrderProcessed event to the Workflow.
  • CancelOrder. This method use OrderWorkflowManager service to send an OrderCancelled event to the Workflow.

OrderWorkflowManagerService

This service envelopes the access to the Workflow so it can be used by OrderService to query and modify the state of a given Order.
It uses an IOrderWorkflowMappingCollection service implementation as it needs to maintain a relation between Orders and its Workflows instances.

Methods

  • CreateOrderWorkflow. Creates a new Workflow instance in the Workflow runtime and uses OrderWorkflowMapping to store the relation between the Order and the Workflow.
  • NotifyOrderCreated. This method sends the Workflow a CreateOrder event to change the state
  • NotifyOrderUpdates. This method sends the Workflow an OrderUpdated event to change the state.
  • NotifyOrderProcessed. This method sends the Workflow an OrderProcessed event to change the state.

// C#
      
public void NotifyOrderProcessed(Guid orderId)
{
    Guid instanceId = GetOrderWorkflowInstanceId(orderId);

    _orderStateMachine.RaiseOrderProcessedEvent(orderId, instanceId);
    // The order is checked, because is transitioning from one state to another.
    NotifyEventRaised(instanceId);
} 
  • NotifyOrderShipped. This method sends the Workflow an OrderShipped event to change the state.
  • NotifyOrderCancelled. This method sends the Workflow an OrderCancelled event to change its state. When the Order is finally cancelled, its Workflow is terminated and its relation with the Order in the OrderWorkflowMapping service is eliminated.
  • GetOrderState. This method returns the state of the Order’s Workflow using a StateMachine instance and querying its CurrentStateName property.

// C#

StateMachineWorkflowInstance stateMachine = new StateMachineWorkflowInstance(_workflowRuntime, instanceId);
string currentStateName = stateMachine.CurrentStateName;
  • GetOrdersByState. This method returns all the orders for a given state, taking all of them from OrderWorkflowMapping and querying the Workflow if the order is in the given state.
  • GetOrderPossibleStates. This method returns the possible state transition using a StateMachine instance.

// C#

Guid instanceId = GetOrderWorkflowInstanceId(orderId);
StateMachineWorkflowInstance stateMachine = new StateMachineWorkflowInstance(_workflowRuntime, instanceId);

foreach (string stateName in stateMachine.PossibleStateTransitions)
{
    possibleStates.Add(StateName2StateEnum(stateName));
} 

IOrderWorkflowMappingCollectione

This service keeps the relation between Orders and Workflows instances. The implementation in this example is LocalOrderWorkflowMappingCollection and it uses a Dictionary to store data.
Using a Dictionary to store this data makes the app useful only for single-user scenario. A multi-user scenario needs another kind of implementation.

Methods

  • Add. Creates a new Workflow instance in the Workflow runtime and uses OrderWorkflowMapping to store the relation between the Order and the Workflow.
  • NotifyOrderCreated. This method sends the Workflow a CreateOrder event.
  • NotifyOrderUpdates. This method sends the Workflow an OrderUpdated event.

OrderPollingService

Methods

  • Start. This method starts a new thread and periodically calls the GetOrders method to get orders from the repository.
  • Stop. This method stops the thread.
  • GetOrders. This private method is periodically called to get Orders using the OrderService and then fires the OrdersLoaded event. The OrderListViewPresenter will be subscribed to this event.

Workflow Integration

Overview

Workflow integration is made by using a CAB service implementing the IOrderWorkflowManage interface.
In this example this implementation named OrderWorkflowManager is used to envelope the communication with the Workflow.
As the orders and theirs are managed by different applications, an IOrderWorkflowMappingCollection service is used to keep the relation between an order and its state.
In this example the LocalOrderWorkflowCollection service is used to keep the mentioned relation.
WorkflowIntegration.png

Creating Workflow Runtime using App.config

In this example the WorkflowRuntime instance is created using the constructor overload that receives a section name of the App.config as a parameter to get the WorkflowRuntime configuration.
In the OrderWorkflowRuntimeSection an ExternalDataExchangeService instance is added to the WorkflowRuntime services collection as follows:

XML

<add type="System.Workflow.Activities.ExternalDataExchangeService, System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" ConfigurationSection="OrdersDataExchangeServicesSection"/>

The ConfigurationSection parameter accepts another section were the ExternalDataExchangeService services can be added.
In the OrdersDataExchangeServicesSection an implementation of the IOrderStateMachineDataExchangeService is added to the ExternalDataExchangeService services collection as follows:

XML

<OrdersDataExchangeServicesSection>
    <Services>
        <add type="OrderWorkflow.OrderStateMachineDataExchangeService, OrderWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </Services>
</OrdersDataExchangeServicesSection>

To summarize, this code create an instance of the OrderStateMachineDataExchangeService to add it to the WorkflowRuntime Services collection.
The OrderStateMachineDataExchangeService is the service by which the SCSF application interacts with the workflow.

Obtaining an OrderStateMachineDataExchangeService instance

As we need the OrderStateMachineDataExchangeService instance inside WorkflowRuntime to interact with the Workflow, we obtain this instance from it.
Getting the created instance of the OrderStateMachineDataExchangeService from the WorkflowRuntime Services collection is done as follows:

// C#
ExternalDataExchangeService dataService = _workflowRuntime.GetService<ExternalDataExchangeService>();

 _orderStateMachine = (OrderStateMachineDataExchangeService)dataService.GetService(typeof(OrderStateMachineDataExchangeService));

Example of interaction

Creating an order and set it to opened state

To accomplish this, the OrderService does the following.
CreatingAnOrderAndSetItToOpenedState.png
These steps are implemented by the following code, extracted from the SaveOrder() method of OrderService:

// C#

_repository.Insert(order);
// Create a workflow instance and maps it to the order in the repository.
_workflow.CreateOrderWorkflow(order.Id);
// Set the order state to opened.
_workflow.NotifyOrderCreated(order.Id);

This code snippet shows how OrderService use OrderWorkflowManager to interact with the Workflow components.
Following are described the methods used in SaveOrder():

CreateOrderWorkflow

The method follows these steps:

// C#

GuardOrderExistsInWorkflow(orderId);
Guid instanceId = StartNewWorkflow();

lock (_orderWorkflowMapping)
{
    _orderWorkflowMapping.Add(orderId, instanceId);
} 
  • 1. Ensures that only one Workflow is created for each order.
    • It uses OrderWorkflowMapping to verify if a Workflow already exists for this given order.
  • 2. Get a new WorkflowInstance using StartNewWorkflow().
    • It is done by using CreateWorkflow() method of WorkflowRuntime
    • It starts the new Workflow calling it Start() method

// C#

WorkflowInstance instance = _workflowRuntime.CreateWorkflow(typeof(OrderStateMachine));
instance.Start();
  • 3. Add the relation between Order and Workflow into the OrderWorkflowMapping service
    • This is done to abstract the logic of the Workflow.
    • The OrderWorkflowMapping is locked to ensure only one Thread has access to it.

NotifyOrderCreated

The method follows these steps:

// C#

Guid instanceId = GetOrderWorkflowInstanceId(orderId);

_orderStateMachine.RaiseOrderUpdatedEvent(orderId, instanceId);
  • 4. Gets the Workflow instances for a given Order.
    • Use OrderWorkflowMapping to get the corresponding Workflow’s InstanceId. This was encapsulating part of the Workflow logic.
  • 5. Calls RaiseOrderCreatedEvent method of OrderStateMachine.
    • The OrderStateMachineDataExchangeService instance previously obtained is used to interact with the Workflow.
These are the basic steps to send messages to the Workflow, making it changing from one state to another.

Last edited Oct 31, 2007 at 3:03 PM by mconverti, version 7

Comments

No comments yet.