Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de Usuários
»Células Acadêmicas«
intcontpiada : 118
Voodoonet
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
Faça um pequeno teste com 10 questões de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programação com nosso treinamento on-line de lógica de programação
.:.
Veja nosso calendário de treinamentos
Gostou da Página?
Então

para um amigo!
 





Por Dennes Torres
dennes@bufaloinfo.com.br
Dennes Torres possui as certificações MCAD, MCSD,MCSE, MCDBA e MCT. Atualmente atua Como diretor da Búfalo Informática, líder do grupo de usuários DevASPNet no Rio de Janeiro e membro da liderança dos grupos getWindows e devSQL, também do Rio de Janeiro, podendo sempre ser encontrado na lista de discussão do grupo DevASPNet (devaspnet-subscribe@yahoogrupos.com.br) bem como nas reuniões do grupo. Mantém dois blogs em http://cidadaocarioca.blogspot.com

Criando workFlows com o WorkFlow Foundation

Pesquisa personalizada
Pesquisar Dicas:







Junto com o lançamento do Windows Vista, previsto para o final do ano, será lançado também um conjunto de APIs que foi inicialmente chamado de WinFx.

Esse nome começou a causar confusão, pois muitos já as estavam chamando de APIs do Windows Vista. Na verdade este conjunto de APIs poderá ser instalado nos sistemas anteriores, tal como Windows XP, 2000 e 2003.

Para resolver (?) o problema de nomenclatura o WinFX passou a se chamar .NET Framework 3.0, com lançamento previsto para junto do Windows VISTA. O framework 3.0 trará 3 novos conjuntos de APIs que serão acrescentados aos recursos que já conhecemos do framework 2.0 : O Windows Presentation Foundation, o Windows Communication Foundation e o Windows WorkFlow Foundation

Neste artigo falaremos sobre o WWF, começando por falar sobre onde os workFlows se encaixam na produção de software.

Afinal, o que são workFlows ? WorkFlows são processos de negócio que seguem um determinado fluxo. Por exemplo, a obtenção de um reembolso de despesa dentro de uma empresa segue um fluxo determinado, isso é o que chamamos de workFlow.

Primeiramente é necessário distinguir entre workFlow e orchestration. WorkFlow é o nome dado a um fluxo quando existem pessoas envolvidas no fluxo. Orchestration é um fluxo que envolva apenas processamento, sem ação humana. Atualmente temos o BizzTalk Server para realizar Orchestration, com fluxos que envolvam diversas aplicações.

O WWF irá realizar as duas tarefas, tanto workflows como orchestration. Passa a utilizar o termo workFlow para se referir de forma genérica a ambas as tarefas.

Ok, o workFlow é um fluxo. Mas todo processo de negócio não é, de fato, um fluxo ?

Bingo ! Todo processo de negócio é um fluxo. Ocorre que hoje as aplicações para criação de workFlows são aplicações de terceiros, caras, então na maioria dos casos desenvolve-se o workFlow simplesmente pelos métodos tradicionais de desenvolvimento.

Mas quando o desenvolvimento de workFlow, com aplicação própria para isso, é necessário ? Simples : Quando o processo for muito grande e/ou for alterado com frequencia. Manipular isso na programação em camadas tradicional gera uma grande dificuldade de manutenção. É ai, para estes casos, que surgem as aplicações para desenvolvimento de workFlows. Então o ponto chave é ** Simplicidade na manutenção de processos ** . Quando falamos em workFlows é disso que estamos falando, podermos dar manutenção não só em código mas em processos com simplicidade.

Então, o WWF vai substituir aplicações de terceiros para desenvolvimento de workFlows ?

O WWF não foi feito para isso. Ele não é uma aplicação final, para um usuário final de processos. Ele é um conjunto de APIs para o desenvolvimento de aplicações que lidem com workFlows. O próprio BizzTalk Server vai ganhar uma versão nova, posteriormente, baseada no WWF. A qualidade das aplicações para workFlow tendem a aumentar, além disso processos de negócio que antes não utilizavam recursos específicos de workflow agora terão tais recursos a disposição, facilitando a manipulação de processos nas empresas e tornando as empresas ágeis.

Então, agora que temos uma visão geral deste cenário, vamos entender melhor o funcionamento do WWF, para isso vamos analisar os diversos "componentes" que o formam : WorkFlows, Hosts, Comunicação de saida, comunicação de entrada.

Arquitetura Básica

WorkFlows

Os recursos para a montagem dos workFlows precisam ser flexiveis o suficiente para permitirem a geração de orchestration e também a geração de workflows com intervenção humana, que podem durar dias ou meses para se completar.

Hosts

Assim como todo o resto, os workFlows também precisam de um processo para roda-los. É o que chamamos de um host para os workFlows. O WWF não possui um host específico, é necessário que nós façamos a criação de um host.

Criar um host não é difícil com os recursos do .NET e do WWF, mas é importante observar que existem alguns desafios importantes nesta criação :

O workFlow envolve a participação de diversas pessoas, em um ambiente distribuido, portanto o workflow tem que estar disponível de forma distribuida.

O workflow pode durar dias ou até semanas para se encerrar. Portanto o host é responsável por manter o fluxo disponível durante toda a execução do fluxo, mesmo em casos extremos, como uma simples falta de luz.

O host deve gerenciar inúmeras execuções do fluxo simultaneamente, atendendo a inúmeros usuários. Com isso deve também fornecer recursos para que administradores de TI possam acompanhar os processos em execução

Comunicação de saida

Durante a execução do fluxo, o workFlow necessita executar tarefas que envolvem o negócio da aplicação. Para isso a aplicação deve fornecer uma classe na qual o fluxo possa fazer o disparo de métodos, gerando os resultado desejados no negócio da aplicação.

Como trata-se de uma comunicação entre 2 aplicações diferentes - o workflow, rodando no host e a aplicação - utilizamos interfaces para realizar essa comunicação.

Comunicação de entrada

Durante a execução do fluxo, o workflow precisa obter respostas da aplicação. Por exemplo, o workFlow pode encaminhar dados para serem aprovados por um gerente e precisará aguardar a aprovação.

Desta forma, quando a aprovação ocorrer será necessário que a aplicação dispare um evento que será visto pelo workFlow. Assim sendo a aplicação e o workFlow precisarão compartilhar a definição deste evento. Além disso não deve esquecer que estamos falando de um disparo entre aplicações diferentes.

Outra questão importante é que quando o host recebe a ocorrência de um evento ele terá, num dado momento, inúmeros fluxos executando. O disparo do evento, portanto, precisa possuir uma indicação de a qual fluxo o evento será destinado.

Agora que você já tem uma noção dos desafios envolvidos em cada um destes tópicos, vamos nos aprofundar mais e analisar como esses problemas são resolvidos no WWF

Mais detalhes técnicos

WorkFlows

Os workFlows são formados por um conjunto de atividades que determinam o fluxo de execução. O WWF já fornece diversas atividades para o controle do fluxo, sendo que podemos com facilidade criar novas atividades.

Como devem dar suporte tanto a workFlows como a Orchestration, temos dois tipos de workflows distintos : WorkFlows sequenciais, mais indicados para trabalho de orchestration (mas não exclusivamente) e State Machine workflows, que nos fornecem mais facilidade para prever os inúmeros eventos que podem ser causados pela ação humana, bem como a transição entre estes eventos.

A criação do workFlow é feita de forma semelhante ao desenvolvimento atual : Um designer para montagem visual com o code-behind sendo gerado automaticamente. Sendo que a geração do workFlow pode ser feita toda em código ou pode ser dividida em um arquivo de código e um arquivo de definições, utilizando uma nova escrita, XOML.

Hosts

O processamento dos workFlows é feito por um componente chamado WorkFlow RunTime. O workFlow runtime é, basicamente, uma classe, a qual pode ser instanciada e através de um método é feito o inicio do processamento.

O runtime foi criado de forma a poder ser utilizado dentro de qualquer tipo de processo. Aplicações windows, aplicações web, qualquer aplicação pode inicializar o runtime e dar inicio a execução de workFlows.

Para entender melhor a criação dos hosts precisamos analisar um conceito fundamental da execução dos workFlows : a necessidade de persistência.

Um workFlow pode rodar durante horas, dias ou até mesmo semanas. É impraticavel que durante todo este tempo o fluxo esteja "no ar", disponível em memória para a realização do processamento.

A grande duração do fluxo ocorre por estar aguardando ações humanas. Uma confirmação, uma entrada de dados, o workFlow está aguardando algo. Enquanto o fluxo aguarda ele precisa ser persistido em algum local, sendo que banco de dados é apenas um exemplo de um dos locais possíveis.

A persistência é então um dos recursos mais fundamentais de um host. No momento em que um fluxo entra em idle, é persistido e retirado da memória. Quando o host recebe a ocorrencia de um evento para este fluxo (observe a importância de identificar para qual fluxo) este é novamente carregado em memória para dar continuidade ao processamento. Isso é chamado de desidratação (a retirada da memória) e re-hidratação - a recarga em memória.

A arquitetura do runtime é feita de forma a suportar a agregação de serviços, é desta forma que o host cumpre sua tarefa. O host fornece ao runtime classes que se interligam com ele (através de eventos) para a execução dos serviços fundamentais, tal como a persistência.

O WWF fornece classes para a realização dos serviços mais fundamentais : Persistencia, tracking (log de eventos) e controle de multi-threading. Mais uma vez, é muito simples : Basta instanciarmos estas classes, configurarmos e adicionarmos (um simples add) como serviços de nossa instância do runtime.

Essas configurações de serviços podem ser feitas também através de arquivos de configuração da aplicação, app.config ou web.config. Basta adicionarmos as tags corretas e os serviços estarão ativos no runtime. É assim que funciona com a persistência, fazendo o trabalho de hidratação e desidratação automaticamente a partir do momento que está devidamente configurada no arquivo .config.

Com esta visão inicial do serviço de persistência podemos entender melhor as formas de hosting, como windows service se comunicando via remoting, como aplicação web, iniciando workFlows a partir de um site, ou como webService, podendo ser consumido por uma aplicação web ou uma aplicação windows.

Mas falta observar ainda uma possibilidade : Imagine aplicações rodando em máquinas totalmente diferentes, cada uma hospedando o workFlow runtime por conta própria. O serviço de persistência de ambas pode ser configurado para apontar para a mesma base de dados. Assim um workFlow pode ser iniciado na máquina A e no momento em que entra em idle, esperando resposta de alguém, é persistido na base. A máquina B, ao gerar uma resposta, "acorda" o workFlow, o que é possível por estarem compartilhando a mesma base de persistência. Eis então mais uma interessante opção de hosting para o workflow runtime.

Comunicação

A comunicação entre a aplicação e o workFlow precisa seguir uma interface definida entre ambos. Assim tanto os métodos para a comunicação de saida como os eventos para a comunicação de entrada precisam estar definidos em uma interface.

Claro que a aplicação precisa fornecer uma classe que implemente esta interface para que a comunicação se complete, mas não em tempo de desenvolvimento. Durante o desenvolvimento o workFlow apenas conhece a interface.

É apenas em runtime que o host gera uma instância da classe que implementa a interface - sim, a classe precisa estar no host - e insere esta classe na forma de um serviço para o workflow runtime. O workFlow conhece a interface, foi construido com base nela, então procura entre os serviços uma instância que implemente a interface para fazer os disparos. Se encontrar mais de uma, na dúvida não dispara nenhuma.

A interface precisa estar marcada com o atributo DataExchangeService para ser reconhecida pelo workFlow.

Comunicação de saida

Qualquer método é aceito na comunicação de saida, desde que a interface esteja marcada com DataExchangeService

Comunicação de Entrada

Quando um evento ocorre o runtime precisa identificar a que instância de fluxo ele se refere. Por isso os eventos para a comunicação de entrada precisam receber um parâmetro derivado da classe ... . Você precisa criar uma classe derivada desta e definir que seu evento a receberá como parâmetro.

O construtor desta classe irá receber como parâmetro o ID do fluxo para o qual o evento está sendo disparado. Desta forma é feita a ligação do disparo do evento com uma execução específica de um fluxo.

O runtime não escuta os eventos de entrada sozinho. Para tratar os eventos de entrada ele precisa do ExchangeDataService. A instância de nossa classe, que antes seria adicionada como serviço do runtime, passa ser adicionada como serviço do ExchangeDataService e este sim como serviço do runtime.

 

Vamos ver alguns desses conceitos na construção de um pequeno exemplo, apenas um começo que completaremos em artigos futuros :

1) Crie um novo projeto como Empty WorkFlow Project (winHello)

2) Adicione um novo workFlow sequencial (wkHello)

3) Insira uma code activity e chame-a de caHello

4) Adicione no projeto uma referência para System.Windows.Forms

5) Na propriedade ExecuteCode da caHello, digite DizHello e pressione enter

6) Codifique o Hello World

    1     Private Sub DizHello(ByVal sender As System.Object, ByVal e As System.EventArgs)

    2 

    3         MsgBox("Hello World !")

    4     End Sub

7) Adicione um novo projeto, winHostHello

8) Na aplicação windows, adicione referência aos 3 assemblies do WWF

9) Adicione a referência ao projeto do workFlow

10) Programe o start do workflow

    1     Dim wr As New System.Workflow.Runtime.WorkflowRuntime

    2 

    3     Private Sub cmdHello_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdHello.Click

    4 

    5         Dim wi As Workflow.Runtime.WorkflowInstance

    6 

    7         If Not wr.IsStarted Then

    8             wr.StartRuntime()

    9 

   10         End If

   11 

   12         wi = wr.CreateWorkflow(GetType(winHello.wkHello))

   13 

   14         wi.Start()

   15     End Sub

11) Definam o projeto windows como startup project

12) Rodem e testem

13) No código do workFlow, criem uma variável privada, vValor.

14) Ainda no código do workFlow, criem uma propriedade pública, Valor, utilizando a variável vValor

    1     Dim vValor As Integer

    2     Public Property Valor() As Integer

    3         Get

    4             Return (vValor)

    5         End Get

    6         Set(ByVal value As Integer)

    7             vValor = value

    8         End Set

    9     End Property

15) No designer do workFlow, insira um if/Else abaixo da Code Activity, chamem de TestarValor

16) Chamem o primeiro Branch de TestarValorBaixo

17) Configurem a condition como CodeCondition e em condition digitem "TestaValorBaixo" e pressionem enter

A condição que montaremos é bem simples e poderia ser montada com o recurso de ruleConditions existente no workFlow, o que seria muito mais fácil.

Mas na versão beta que estou utilizando existem bugs no desenvolvimento do workFlow com VB.NET. As ruleConditions, em alguns pontos, são vinculadas diretamente com a síntaxe do C#, o que impede que sejam usadas em VB.NET. Isso apenas na versão beta, claro.

18) Codifique a condição

    1     Private Sub testaValorBaixo(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.ConditionalEventArgs)

    2 

    3         e.Result = (vValor < 500)

    4     End Sub

19) Chamem o 2o Branch de ValorAlto

20) Insiram uma codeActivity em cada Branch, chamando-as de caValorBaixo e caValorAlto

21) Em caValorBaixo digitem valorMuitoBaixo na propriedade ExecuteCode, pressionem enter e codifiquem um msgBox.

22) Em caValorAlto digitem valorMuitoAlto na propriedade ExecuteCode, pressionem enter e codifiquem um msgbox

    1     Private Sub valorMuitoBaixo(ByVal sender As System.Object, ByVal e As System.EventArgs)

    2 

    3         MsgBox("Valor muito baixo!")

    4     End Sub

    5 

    6     Private Sub valorMuitoAlto(ByVal sender As System.Object, ByVal e As System.EventArgs)

    7 

    8         MsgBox("Valor muito alto!")

    9     End Sub

23) Cliquem com o botão direito do TestaValor e utilizem Add Branch

24) Movam o novo Branch para o meio dos dois anteriores, arrastando com o mouse

25) Chamem o novo branch de TestarValorIdeal

26) Configurem a condition como codeActivity, chamem de TestaValorIdeal e codifiquem

    1     Private Sub testaValorIdeal(ByVal sender As System.Object, ByVal e As System.Workflow.Activities.ConditionalEventArgs)

    2 

    3         e.Result = (vValor > 500 And vValor < 2000)

    4     End Sub

27) Insira uma codeActivity no novo Branch chamada caValorIdeal

28) Configurem o executeCode da caValorIdeal como ValorIdeal e codifiquem um msgbox

    1     Private Sub valorIdeal(ByVal sender As System.Object, ByVal e As System.EventArgs)

    2 

    3         MsgBox("Valor Ideal !")

    4     End Sub

29) Na aplicação Windows, insira uma caixa de texto chamada txtValor

30) Codifique a passagem de parâmetro para o workFlow

Observe a conversão de dados da textbox. O stringDictionary aceita object, se não houver a conversão, o parâmetro passado será string e ocorrerá um erro no workFlow

    1     Dim wr As New System.Workflow.Runtime.WorkflowRuntime

    2 

    3     Private Sub cmdHello_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdHello.Click

    4 

    5         Dim wi As Workflow.Runtime.WorkflowInstance

    6         Dim parametros As New Dictionary(Of String, Object)

    7 

    8         If Not wr.IsStarted Then

    9             wr.StartRuntime()

   10         End If

   11 

   12 

   13         parametros.Add("Valor", CInt(txtValor.Text))

   14 

   15         wi = wr.CreateWorkflow(GetType(winHello.wkHello), parametros)

   16 

   17         wi.Start()

   18     End Sub

31) Faça um rebuild no projeto e teste

32) Adicione um novo projeto na solução, clInterface, do tipo Class Library

33) Adicione uma referência no projeto clInterface para o Assembly System.WorkFlow.Activities

34) Codifique a interface IHello, marcando-a com o ExternalDataExchange

    1 <Workflow.Activities.ExternalDataExchange()> Public Interface IHello

    2 

    3     Sub ValorMuitoAlto(ByVal valor As Integer)

    4     Sub ValorMuitoBaixo(ByVal valor As Integer)

    5     Sub ValorIdeal(ByVal valor As Integer)

    6 End Interface

35) Faça uma referência do projeto windows, winHostHello, para a interface

36) Faça uma referência do workFlow para a interface

37) Delete as 3 codeActivities nos Brachs do IF/ELSE

38) Insira 3 CallExternalMethod nos Brachs do IF/ELSE

39) No primeiro Brach, chame o callExternalMethod de cemValorBaixo

40) Configure o interfaceType do cemValorBaixo para a interface iHello

41) Na propriedade methodName, selecione valorMuitoBaixo

42) No parâmetro valor, aponte para a propriedade Valor

42) No 2o CallExternalMethod, configure para cemValorIdeal, defina o interfaceType para IHello, o método para valorIdeal e o parâmetor para a propriedade Valor

43) No 3o CallExternalMethod cemValorAlto, defina o interfaceType para IHello, o método para valorAlto e o parâmetro para a propriedade Valor.

44) No projeto Windows, adicione uma nova classe, clHello

45) Codifique a implementação da interface Ihello

    1 Public Class clHello

    2     Implements clInterface.IHello

    3 

    4 

    5     Public Sub ValorIdeal(ByVal valor As Integer) Implements clInterface.IHello.ValorIdeal

    6 

    7         MsgBox("Valor Ideal!")

    8     End Sub

    9 

   10     Public Sub ValorMuitoAlto(ByVal valor As Integer) Implements clInterface.IHello.ValorMuitoAlto

   11 

   12         MsgBox("Valor muito alto!")

   13     End Sub

   14 

   15     Public Sub ValorMuitoBaixo(ByVal valor As Integer) Implements clInterface.IHello.ValorMuitoBaixo

   16 

   17         MsgBox("Valor muito baixo!")

   18     End Sub

   19 End Class

 

46) No formulário, antes de chamar o workflow, crie uma instância da classe clHello e adicione como serviço no runtime

    1     Dim wr As New System.Workflow.Runtime.WorkflowRuntime

    2 

    3     Private Sub cmdHello_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdHello.Click

    4 

    5         Dim wi As Workflow.Runtime.WorkflowInstance

    6         Dim parametros As New Dictionary(Of String, Object)

    7         Dim hello As New clHello

    8 

    9 

   10         If Not wr.IsStarted Then

   11             wr.StartRuntime()

   12             wr.AddService(hello)

   13         End If

   14 

   15 

   16         parametros.Add("Valor", CInt(txtValor.Text))

   17 

   18         wi = wr.CreateWorkflow(GetType(winHello.wkHello), parametros)

   19 

   20         wi.Start()

   21     End Sub

47) Rode e teste

 

Veja também : http://www.msdnbrasil.com.br/mediacenter/authors.aspx?AuthorName=Dennes%20Torres

 

 



Envie seus comentários sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentários nesta página

Veja abaixo os comentários já enviados :

Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1