domingo, 24 de octubre de 2010

1. Requisitos

WWF (Windows Workflow Foundation) necesita las siguientes BD, una para la persistencia y otra para el seguimiento, los script de tablas y procedimientos almacenados son las siguientes:
C:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN
SQL Server for Tracking
DataBase: WorkflowTracking
             * |-> Tracking_Schema.sql
             * |-> Tracking_Logic.sql
SQL Server for Persistence
DataBase: WorkflowStore
             * |-> SqlPersistenceService_Schema.sql
             * |-> SqlPersistenceService_Logic.sql

2. Pasos para crear un workflow

Paso 1: Declarar workflow runtime

Paso 2: Declarar y registrar servicios principales

Paso 3: Declarar workfl0w instance

Paso 4: Cargar y descargar workflow instance

Paso 5: Diseñar el workflow (Basándose en las Actividades Estándar descritas en el paso 3)

3. Actividades estándar

·     Clasificación 1

Custom Workflow Logic: La actividad simple en esta categoría permite adicionar nuestra propia lógica de negocio directamente en el workflow.

Code Activity

Flow Control: Las actividades en esta categoría controlan el flujo de ejecución de un workflow. Incluye mucho de la programación como bifurcaciones y bucles. También permite ejecutar actividades en paralelo, replicación, detención, término, y suspensión de un workflow.

IfElseActivity y IfElseBranchActivity

While

DelayActivity

SequenceActivity

ParallelActivity

ReplicatorActivity

ContionedActivityGroup

InvokeWorkflowActivity

State Management: Las actividades de esta categoría traban con workflow de maquinas de estados. Estas actividades se usan para definir, inicializar, y finalizar un estado, y transición entre diferentes estados.

StateActivity

SetStateActivity

StateInitializationActivity

StateFinalizationActivity

Event Handling: Las actividades de esta categoría son todas relacionadas a los eventos que se disparan y trabajan con actividades hijas que reciben estos eventos. Las actividad fuera de línea actualmente no reciben eventos, pero en vez de esto ellos están contenidos por otra actividad que maneja eventos.

ListenActivity y EventDrivenActivity

EventHandlerActivity y EventHandlerScopeActivity

Local Service Communication: Las actividades son usadas para comunicación entre un workflow y servicio local

CallExternalMethodActivity

HandleExternalEventActivity

Rules: Las actividades en esta categoría están asociadas con el workflow rules engine.

PolicyActivity

Web Service: Las actividades de esta categoría permiten a tu workflow interactuar con servicios web. Usando estas actividades tu puedes invocar un servicio web desde tu workflow o tu puedes exponer un workflow a un cliente de un servició web.

InvokeWebServiceActivity

WebServiceInputActivity

WebServiceOutputActivity

WebServiceFaultActivity

Transactions, Compensation y Sincronización: Las actividades de esta categoria permiten definir una simple actividad que involucra multiples actividades. Tambien incluye actividades que permiten compensar y sincronización de acceso a variables. La compensación es la habilidad de deshacer acciones que ya fueron completadas correctamente.

TransactionScopeActivity

CompensatableTransactionScopeActivity y CompensatableSequenceActivity

CompensateActivity y CompensationHandlerActivity

SynchronizationScopeActivity

Exceptions y Error Handling: Esta categoría de actividades trabajan con excepciones .NET (clases que son asignadas de la clase base Exception). Una actividad es usada para la excepción throw dentro del workflow, mientras otras son usadas para manejar excepciones de tipo throw.

ThrowActivity

FaultHandlerActivity y FaultHandlersActivity

CancellationHandlerActivity

·     Clasificación 2

Basic Activities Operations

Sequence Activity

Code Activity

Throw Activity

FaultHandler Activity

Suspend Activity

Terminate Activity

Calling External Methods and Workflow

Logic Flow Activity

IfElse

While

Replicator

Event Activity

HandleExternalEvent Activity

Delay Activity

EventDriven Activity

Listen Activity

EventHandleScope Activity

Parallel Activities

Parallel Activity

SynchronizacionScope Activity

ConditionedActivityGroup Activity

Crafting Custom Activity

4. Principales propiedades y métodos

WorkflowRuntime: Encola y controla los WorkflowInstance

Properties

IsStarted: Determina que el workflow runtime está corriendo y esta lista para recibir workflow Instances, no se puede adicionar servicios principales (core services) mientras el workflow runtime está corriendo.

Name: Trae o permite setear el nombre asociado con el workflow runtime.

 

Methods

AddService: Adicionar un especifico servicio al workflow runtime.

CreateWorkflow: Crea una instancia del workflow, incluyendo algún especifico parámetro. Si el workflow runtime no está iniciado el método CreatedWorkflow llama al StartRuntime.

GetWorkflow: Recibe una instancia de un workflow especificando el identificador del workflow GUID, si el workflow está en estado inactivo y persiste, es nuevamente cargado y ejecutado.

StartRuntime: Inicia el workflow runtime y invoca al evento Started.

StopRuntime: Detiene el workflow runtime y invoca al evento Stopped.

 

Events

Started: Es invocado  donde el workflow runtime es iniciado.

Stopped: Es invocado donde el workflow runtime es detenido

WorkflowCompleted: Es invocado donde el workflow instance fue completado

WorkflowIdled: Es invocado donde el workflow instance está inactivo, tú tienes la oportunidad de descargarlo de la memoria, siendo almacenado en la base de datos (en caso de que espere un largo tiempo) permitiendo posteriormente traerlo a memoria.

WorkflowTerminated: Es invocado cuando el workflow instance es terminado. El workflow puede ser terminado por el host  llamando al método Terminated del workflow Instance, por la actividad Terminated, o cuando ocurre un error en el workflow runtime.

 

WorkflowInstance: Administra la ejecución de las actividades

Properties

InstanceId: Consigue el identificador unico del workflow instance (un GUID)

WorkflowRuntime: Consigue el workflow runtime para el workflow instance.

Method

ApplyWorkflowChanges: Aplica cambios al workflow instance especificados en el objeto WorkflowChanges. Permitiendo (adicionar, remover o cambiar actividades) mientras se ejecutan,  aunque el workflow instance es suspendido mientras los dinámicos cambios son realizados.

GetWorkflowDefinition: Recibe la actividad principal para este workflow instance.

Resume: Resume ejecuciones de workflow instances suspendidas. Si el workflow instance está en estado suspendido, el workflow runtime invoca el evento WorkflowResumed antes que la ejecución del workflow instance sea iniciado.

Start: Inicia la ejecución del workflow instance, en la actividad principal llama al ExecuteActivity del workflow instance. Si se encuentra una excepción al iniciar se llama al evento Terminate donde la propiedad Message tiene error que ocurrió.

Suspend: Sincronamente suspende el workflow instance. Si el workflow instance está suspendido no ocurre nada. Si la instancia está corriendo el workflow runtime suspende el workflow instance, setea SuspendOrTerminateInfoProperty a una cadena y es pasada dentro del Suspend, y se invoca el evento WorkflowSuspended.

Terminate: Sincronicamente termina el workflow instance. Cuando el host solicita la terminación del workflow instance, el workflow runtime mata la instancia y trata de persistir el estado final de la instancia. Entonces el workflow instance setea SuspendTerminateInfoProperty la razón de Terminate. Finalmente se invoca al evento WorkflowTerminated donde la propiedad Message de un WorkflowTerminatedException del WorkflowTerminatedEventArgs. Si otra dieferente excepción es invocada durante la persistencia, pasa la excepción en el WorkflowTerminatedEventArgs.

ExecutionStatus

Canceling: La actividad está en proceso de cancelación

Closed: La actividad es cerrada

Compensating: La transacción ha fallado, la actividad ha iniciado la acción de compensación

Executing: La actividad está actualmente corriendo

Faulting: La actividad está sosteniendo una excepción

Initialized: La actividad ha sido inicializada pero aun no está corriendo

 

Activity

Properties

Description: Lee o setea la descripción de la actividad definida por el usuario

Enabled: Lee o setea un valor que indica si la instancia está habilitada para la ejecución y la validación

ExecutionResult: Lee el ActivityExecutionResult del último intento para correr esta instancia (Canceled, Compensated, Faulted, None y Succeded)

ExecutionStatus: Lee el estado del workflow de uno de los valores ActivityExecutionStatus (Canceling, Closed, Compensating, Executing, Faulting, y Initialized)

Name: Lee o setea el nombre de esta actividad

Parent: Lee esta actividad que incluyeesta actividad

WorkflowInstanceId: Lee el identificador de la instancia del workflow asociado a esta actividad

Method

Cancel: Cancela la ejecución de una actividad

Clone: Retorna un “deep copy” (“deep copy” significa clonar una actividad con toda su información interna)

Execute: Corre de forma síncrona la actividad

GetActivityByName: Si es ejecutada en una actividad compuesta, retorna el nombre de la actividad compuesta

Load: Carga una instancia de una actividad desde un stream

RaiseEvent: Levanta un evento asociado con el DepencyProperty

RaiseGenericEvent<T>: Levanta un evento asociado con la referencia de DepencyProperty. El efecto de RaisedEvent y RaisedGenericEvent es lo mismo. El RaisedEvent usa la dependencia genérica directamente mientras el RaisedGenericEvent usa la versión genérica (template).

Save: Graba una copia de la actividad a un stream

ActivityExecutionContext

Muchos de los métodos de los objetos de la actividad requieren un ActivityExecutionContext como objeto de entrada. El objeto de ActivityExecutionContext es creado cuando el workflow runtime encola tu instancia para su ejecución. Sin embargo no se crea directamente. El workflow runtime lo crea por ti.

El objeto de ActivityExecutionContext tiene como propósito proveer a la actividad métodos y servicios al workflow instance, así como su inicialización, cronómetro, y el fuljo de ejecución en general.

Este objeto tiene el mismo propósito que en ASP.NET del objeto de contexto System.Web.HttpContext. Y en .NET Framework del objeto de contexto System.Threading.Thread.CurrentContext. El objetivo de todos estos objetos de contexto es el mismo proveer un lugar de almacenamiento y fácil acceso a información específica de la instancia actual en ejecución. En este caso es una instancia de una actividad en ejecución.

Dependency Properties

Normalmente, si tu creas una propiedad para una clase, tu también creas un campo que almacena el valor de la propiedad. Este tipo de código es común:

    class MyClass

    {

        protected Int32 _x=0;

       

        public Int32 X

        {

            get { return _x; }

            set { _x = value; }

        }

    }

 

El campo _x es mas formalmente llamado backing store. La clase en este ejemplo provee un backing store para la propiedad X.

Tanto WF y WPF sin embargo necesitan acceder a las propiedades de tu clase. WPF necesita determinar el tamaño y el espacio de los controles en los contenedores así como objetos necesarios para su renderización. WF necesita la dependencia de propiedades para facilitar el activity binding, el cual es un proceso que permite relacionar diferentes actividades a la misma propiedad. La clase del WF ActivityBind facilita esta tarea.

Para facilitar la asociación y vinculación de propiedades, el backing store para tu clase propiedades puede ser alterado desde tu clase al .NET runtime. Los datos son almacenados por el .NET. En este sentido, es como tener un espacio lleno de casilleros. Tú no tienes que construir un edificio e instalar los casilleros, pero tú puedes usarlos cuando lo necesites. En este caso con .NET tu registras o pides un casillero, y .NET lo provee y la manera de cómo acceder dentro del casillero. Estos casilleros son llamados DependencyProperties.

Volveremos a revisar el código anterior, pero usaremos un DependencyProperties como un backing store para la propiedad X:

    class MyClass

    {

        public static DependencyProperty XProperty = DependencyProperty.Register(“X”, typeof(System.Int32), typeof(MyClass));

       

        public Int32 X

        {

            get { return ((Int32) (base.GetValue(MyClass.XProperty))); }

            set { base.SetValue(MyClass.XProperty, value); }

        }

    }

Los métodos de acceso al backing store son dados por el .NET runtime y usados para desarrollar custom activity.

Activity Validation

Algunas de las actividades implementan diferentes algoritmos de validación. Si nosotros compilamos un código con errores de validación, la compilación fallará. Nosotros deberíamos corregir las diferentes validaciones antes de compilar y ejecutar nuestro código del workflow.

Workflow Types

Se tiene los siguientes tipos de workflow:

Sequential: Las tareas son ejecutadas autónomamente con poca dirección El workflow controla la ejecución de las tareas. La interacción con el usuario no es requerida. La actividad principal está en la actividad SequentialWorkflow. Tiene un tipo de proyecto en visual studio de nombre sequential workflow.

State-machine: Las tareas dependen del control de guía de ejecución. Hay mucha interacción el usuario. La actividad principal es la actividad StateMachineWorkflow. Tiene un tipo de proyecto en visual studio de nombre state-machine workflow.

Rules-based: Las reglas de negocio existen para resolver complejas decisiones, y ni un workflow secuencial o un workflow de estados directamente aplican. Combina las actividades Policy  y las reglas de condiciones para ejecutar tareas del workflow basadas en reglas de negocio específicas. Puede tener como actividad principal a un SequentialWorkflow o un StateMachineWorkflow. No tiene un tipo de proyecto en visual studio básicamente se inicia con un proyecto sequential workflow y adicionamos rules-based activities (actividades basadas en reglas).

 

Pluggable Services

Son servicios que se seleccionan de una carta para optimizar una específica tarea. Por ejemplo, hay servicios que administran  threading, tracking, transactions, y otros. Tú seleccionas el servicio correcto para tu workflow e incluso se puede crear uno propio o personalizado.

Base Worflows Services

WorkflowPersistenceService: Clase base abstracta donde todos los servicios de persistencia son derivados

WorkflowQueuingService: Clase base provee métodos para administrar la cola de workflow asociados con una instancia del workflow

WorkflowRuntimeService: Clase abstracta donde los servicios principales del proceso (workflow runtime core services) son derivados.

WorkflowSchedulerService: Clase base que crean todas las clases que crean hilos para correr una instancia del workflow en el host workflow runtime

WorkflowSuscriptionService: Clase base que administran suscripciones para el workflow runtime

WorkflowTransactionService: Clase base para todos los servicios de transacción

TrackingService: Clase base provee una básica interfaz entre un servicio de seguimiento y la infraestructura de seguimiento (runtime tracking infrastructure)

El Default WorkflowSchedulerService justamente se basa en el WorkflowSchedulerService. Pero si tu quieres proveer thread, tu puedes usar el ManualWorkflowSchedulerService, también usaremos el SqlTrackingService que se basa en la clase base TrackingService.

 

Workflow Tracking

Recordemos que WF tiene como principal servicio de navegación al SqlTrackingService. Sin embargo tenemos dos servicios adicionales como el ConsoleTrackingService y el SimpleFileTrackingService que permiten escribir información de seguimiento en la consola de windows o en un archivo en vez de en una base de datos en Microsoft SQL Server.

SqlTrackingService

Servicio de seguimiento del WorkflowRuntime seguimiento del WorkflowInstance, eventos disparados (tracking records), y actividades individuales de un workflow

Event Tracking Object

 Eventos de actividades, eventos de workflow y eventos de usuarios,  el seguimiento de objetos ActivityTrackingPoint o ActivityTrackingLocation, los eventos incluidos  son cosas como actividades canceladas, eventos de errores, y eventos de ejecución como por ejemplo cuando el workflow inicia o se detiene, cuando se crea la instancia, se pausa, o se termina.

El tracking profile nos permite determinar que eventos queremos filtrar para el seguimiento.

ActivityDataTrackingExtract: Especifica una propiedad o campo a ser extraído desde una actividad y envía al servicio de seguimiento una colección de anotaciones donde corresponde un punto de seguimiento.

ActivityTrackingCondition: Representa el resultado de la comparación de una actividad con un valor con una especifica comparación

ActivityTrackingLocation: Define la localización de una actividad correspondiente a un evento de una actividad en la ejecución de una instancia de un workflow.

ActivityTrackingRecord: Contiene los datos enviados a un servicio de seguimiento por la infraestructura de seguimiento (runtime tracking infrastructure) donde un coincide un ActivityTrackPoint.

ActivityTrackPoint: Define un punto de interés que es asociado con el cambio del estado de una actividad en ejecución.

SqlTrackingQuery: Provee métodos y propiedades para acceder a la información de seguimiento almacenada en la base de datos SQL por el SqlTrackingService.

SqlTrackingQueryOptions: Contiene propiedades que son usadas para setear objetos SqlTrackingWorkflowInstance retornados por el método SqlTrackingQuery. GetWorkflows

 SqlTrackingWorkflowInstance: Retornado a cada SqlTrackingQuery.TryGetWorkflow o SqlTrackingQuery.GetWorkflows para proveer acceso a la colección de datos de seguimiento por el SqlTrackingService en una base de datos SQL para una especifica instancia.

TrackingProfile: Filtra eventos de seguimiento, y retorna los registros basados al filtro para un servicio de seguimiento. Hay tres tipos de eventos de seguimiento que pueden ser filtrados: eventos de estados de la actividad, estados de los eventos del workflow, y eventos del usuario.

UserTrackingLocation: Especifica localizaciones definidas por el usuario que corresponden a un evento del usuario en la ejecución principal de una instancia del workflow

UserTrackingRecord: Contiene datos enviados al servicio de seguimiento por la infraestructura de seguimiento (runtime tracking infrastructure) donde coincide un TrackingPoint.

UserTrackPoint: Define un punto de interés que es asociado con un evento de usuario

WorkflowDataTrackingExtract: Especifica una propiedad o campo a ser extraído desde un workflow y envía un servicio de seguimiento conjuntamente con una asociada colección de anotaciones donde coincide un punto de seguimiento

WorkflowTrackingLocation: Define una capacidad al workflow de localización que corresponde a un evento del workflow en la ejecución principal de una instancia del workflow

WorkflowTrackingRecord: Contiene los datos enviados  al servicio de seguimiento por la infraestructura de seguimiento donde coincide un WorkflowTrackPoint

WorkflowTrackPoint: Define un punto de interes que es asociado con un evento del workflow

SqlWorkflowPersistenceService

Permite unload y load WorkflowInstance después de un ActivityExecutionContext completa y se cierra (unloaded)

Cuando la actividad entra al estado de pausa (opcionalmente unloadable y persistable)

Un TransactionScopeActivity se completa (unloaded)

Un Activity tiene el atributo PersisOnCloseAttribute se completa (unloaded y opcionalmente persistable)

Donde se llama explícitamente al WorkflowInstance.Unload o WorkflowInstance.TryUnload (unloaded y persisted)

La actividad de Delay usa automáticamente persistencia proveyendo un parámetro al constructor del servicio de persistencia

Tracking User Events

SqlTrackingService porque es una parte del WF, Es la capacidad de los eventos de seguimiento que son heredados WF. Las actividades soportan un método de nombre de TrackData. TrackData tiene dos versiones: uno toma un objeto para ser almacenado en la base de datos de seguimiento y el otro acepta una cadena como clave que será almacena como un objeto, ambos en la tabla ActivityInstance.

    this.TrackData(“Delay completed”)

 

Serialization Markup

WF incluye la clase WorkflowMarkupSerializer (localizada en el espacio de nombre System.Workflow.ComponentModel.Serialization), provee una forma para convertir de un formato a otro. Usando el metodo Serialize de esta clase, tu puedes crear un archivo de un modelo en memoria de un workflow. El método Deserialize realiza el proceso inverso, leyendo un archivo y pasando un objeto que contiene la definición del modelo de un workflow.

También incluye otras clases que derivan de WorkflowMarkupSerializer. Por instancia, la clase ActivityMarkupSerializer contiene maneja la serialización de simples actividades mientras la clase CompositeActivityMarkupSerializer contiene código para actividades compuestas.

La habilidad de convertir fácilmente el modelo del workflow entre formatos es importante si necesitamos hostear el diseño del workflow en la aplicación, o de otra manera provee la personalización del modelo del workflow en la aplicación.

 

Compilation Workflow

Otra opción disponible es compilar el workflow markup (XAML) en un ensamblado. Tú debes escoger esta opción si tú necesitas flexibilidad al definir el modelo del workflow markup con mejor control y tipo seguro.

Cuando tu cargas un workflow markup directamente en el WorkflowRuntime, ello primero parsea y valida antes de crear una instancia del workflow. Algunos errores en el markup son descubiertos solamente, como tú intentas usarlo. Por otro lado, precompilando el workflow markup en el ensamblado optimizando el parseo o validación antes del proceso. Los errores en el markup son descubiertos antes que se cree una instancia del workflow. Esto en realidad es un argumento pasado de compilado vs lenguajes intérpretes. El mecanismo depende de los requerimientos de la aplicación.

Para compilar el workflow markup dentro de ensamblados, también elimina el ligero golpe de optimización asociado con el parseo y validación el markup en el runtime. Para algunas aplicaciones, la distribución de los archivos markup también complica el despliegue de la aplicación e incluso el riesgo de la seguridad, puesto que ellos son fáciles de revisar por algún editor de texto.

WF también provee la siguiente línea de comando wfc.exe ofrece la misma capacidad que la clase WorkflowCompiler. El wfc.exe (workflow compiler) es distribuido con el SDK.

Por ejemplo el comando wfc.exe compila el markup y los archivos .rules.

wfc.exe SerializedCodedWorkflow.xoml /target:assembly /debug:- /resource:ProWF.NewWorkflowClass.rules /reference:WF_WSSerializationMarkupRule.exe /out:NewAssembly.dll

 

Deserializing Markup

La clase WorkflowMarkupSerializer puede ser usado cuando se necesite deserializar el archivo workflow markup en un objeto. El método Deserialize acepta un objeto XmlReader y retorna un objeto que representa el modelo del workflow. Tú necesitas deserializar el archivo markup si quieres modificar el modelo del workflow en código.

El archivo markup deserializado es una tarea, pero no necesita una especial atención para el proceso si el archivo markup contiene la referencia a tipos personalizados. El proceso de la deserialización debería ser capaz de resolver todas las referencias Type, por otro lado las fallas. El archivo markup referencia a un Type personalizado, tú debes proveer el WorkflowMarkupSerializer con referencia al ensamblado contiene el Type.

Esto se logra con un objeto DesignerSerializationManager que contiene un TypeProvider. Tú adicionas la referencia del ensamblado por medio de los métodos del TypeProvider.