Este tutorial é uma continuação de meus estudos sobre desenvolvimento de processos complexos usando Node.js e a ferramenta de workflow Camunda.
No passo a passo anterior modelamos um processo de duas etapas muito simples, o que não demonstra muito bem as vantagens desta arquitetura. Claro que editar um fluxo BPMN é muito mais amigável para pessoas que não são desenvolvedoras do que ficar editando código, mas é quando o processo é complexo de verdade que entram as vantagens desta abordagem em cena.
Atividades Humanas
Por exemplo, e se uma das etapas do processo do software exige intervenção humana? Isso é facilmente resolvido adicionando uma User Task. Para fazê-lo eu vou editar o processo de enviar email mudando o sue tipo de Service Task para User Task, usando o ícone de chave inglesa quando ele está selecionado.
Talvez, por algum motivo estranho, após o usuário ser salvo no banco por uma API, deve ser derivado para um humano enviar um e-mail para ele, manualmente. Ou seja, o processo vai ficar preso ali até a tarefa manual ser realizada.
Toda User Task possui um encarregado. Para defini-lo, clique na User Task enviar e-mail e depois na aba direita de propriedades, definindo o assignee como sac (serviço de atendimento ao cliente).
Esse encarregado deve ter uma maneira de ver os usuários que foram salvos e que ele precisa enviar email, bem como ter uma forma de dizer que enviou este email. Aí que entram os forms do Camunda, um recurso simples porém útil para as tarefas manuais.
Para criar um form para esta Human Task, basta ir na janela propriedades dela, na aba Forms. Adicione os seguintes campos (não adicione ID no form e use o mesmo padrão de nome de variáveis JS):
- dataEnvio (Date);
- funcionario (String)
Agora faça deploy do seu processo (com o Camunda rodando, obviamente) e inicie um novo cadastro de usuário através do POSTMAN, como fizemos no tutorial anterior (não esqueça de deixar o worker Node.js rodando).
Quando o processo iniciar através do POST, ele vai enfileirar a etapa que vai ser consumida pelo worker. Na sequência, vai enfileirar a task para um humano fazer manualmente, que é o que nos interessa agora.
Quem é o responsável que definimos para esta atividade? O sac, mas ele não existe ainda, já que por padrão o Camunda apenas deixa criado um usuário demo.
Para criar este usuário sac (que depois vai ser usado por alguém para fazer suas tarefas manuais), vá na área de administração (http://localhost:8080/camunda/app/admin/default/#/) e clique na opção “Create New User”, que é bem auto explicativa.
Depois de criar o usuário, temos de dar permissão para ele ver a Task List do Camunda, onde vão cair as suas atividades manuais. Para fazer isso, ainda como admin (usuário demo), vá em Authorizations e “Create New Authorization”, dando permissão para o usuário sac acessar a Task List.
Note que está área de autorização é bem mais poderosa que isso, sendo que você pode aplicar regras a grupos, por exemplo, e mexer no acesso não apenas da Task List como do Cockpit também, caso tenham pessoas que vão fazer o monitoramento dos processos da empresa.
Agora, faça sign out do usuário demo e acesse a Camunda Task List no browser ( http://localhost:8080/camunda/app/tasklist), autenticando-se como sac. Você terá acesso à lista de tarefas que caíram para este usuário:
Ao preencher o formulário (que não colocamos validação, mas poderíamos) e clicar em Complete, o atendente do SAC destrava o processo deste usuário e ele seguirá seu fluxo normalmente.
Importante: cada vez que você faz um deploy do seu modelo no Camunda, ele cria uma nova versão do fluxo. Processos iniciados em versões anteriores se mantém nas suas versões originais. Tome cuidado!
Nestes casos, você pode migrar instâncias de um processo para outro ou então excluir instâncias em versões antigas de processo.
Tomada de Decisão
Seguindo na linha de mostrar fluxos cada vez mais complexos e portanto mais interessantes de serem feitos em uma ferramenta de BPM do que em linguagem de programação, vou falar agora de tomada de decisão, ou desvios de fluxo.
Em BPMN isso é chamado de gateways, que podem ser exclusivos, inclusivos, em paralelo ou de sincronização, mas falaremos aqui dos exclusivos, que seriam o equivalente em BPMN dos if/else que temos nas linguagens de programação. Dependendo de uma condição executamos um processo, caso contrário, executamos outro.
Modifique o seu processo para ficar igual ao abaixo, onde adicionei um gateway antes de salvar o usuário no banco, em que vamos verificar se ele é maior de idade ou não.
Agora, vamos adicionar a expressão condicional em cada uma das setas (fluxos) do nosso processo. Vamos começar pela seta “Sim”. Selecione ela e depois vá na aba propriedades, escolha o Condition Type para Expression e adicione a seguinte expressão “${age>=18}”, sem aspas, como mostra na imagem abaixo.
Faça o mesmo para o fluxo “Não”, mas ajustando a expressão de acordo (este padrão de expressão se chama Java Unified Expression Language).
Salve e faça o deploy deste novo processo e, para testá-lo, precisamos mudar levemente o payload do nosso HTTP POST via Postman, incluindo um campo age, como abaixo.
Agora você pode testar. Quando enviar requisições com idade menor de 18, o fluxo do processo será finalizado antes de salvar no banco, e isso pode ser observado no Camunda pois não irá gerar atividade humana.
Já quando você enviar requisições com idade igual ou superior, o worker vai funcionar e vai cair na fila do SAC para atividade manual.
Aplicando Regras de Negócio
Apesar dos gateways nos permitirem aplicar regras de negócio muito simples em nossos workflows, eles são bem limitados e/ou exigiriam muitos gateways para implementar regras complexas. Aí que entram as Business Rule Tasks.
Vamos modificar o nosso processo para, após a atividade manual de envio de e-mail, o cadastro cai para uma análise feita a partir de regras de negócio que iremos definir. Modifique o seu processo para que fique igual à imagem abaixo.
Edite as propriedades dessa Business Rule Task para que o Implementation seja DMN (já vamos falar disso), o “Decision Ref” seja “analisar-cadastro”, “Result Variable” para approved e “Map Decision Result” como “singleEntry”.
Salve tudo e faça novo deploy deste processo.
Esta etapa do processo vai esperar que uma DMN (Decision Model and Notation) exista para, dado um conjunto de dados de uma instância de processo (nosso usuário), ela confira uma série de regras que definirmos para retornar uma variável approved com true ou false (isso porque configuramos assim, poderia ser retornado um objeto mais complexo).
Para criar uma nova DMN Table a partir do menu File do Camunda Modeler. A primeira coisa que você deve fazer com esta DMN Table é definir o seu nome e o seu ID, este último exatamente igual ao que colocou na propriedade “Decision Ref” da Business Rule Task anterior. Antes de definirmos as nossas regras de negócio, vale ressaltar que fazer regras simples é muito fácil e rápido, mas regras complexas é uma espécie de arte e vou tentar te poupar trabalho aqui, mas não faço milagre, ok?
No tutorial oficial de DMN, eles mostra a regra mais simples possível, que é do input ser igual a uma das regras (linhas) da DMN. Deu match, retorna output à direita. No entanto, quando eu quis fazer algo mais elaborado, quebrei um pouco a cabeça pois minhas expressões não funcionavam. O segredo aqui é: trate o input antes de mandar pra DMN (via um worker Node, por exemplo) ou no próprio campo Input Expression, que é o que vou mostrar aqui. Isso porque a tabela de decisão aceita expressões FEEL muito limitadas e o ideal é usar apenas os matches comuns mesmo.
Sendo assim, adicione apenas um input na sua DMN clicando no sinal de ‘+’, coloque no Input Label o nome ‘bonito’ do campo (email), em Input Variable coloque o nome da variável que a DMN vai receber do estágio anterior do processo (email também), deixe o tipo de retorno como boolean e escolha a opção script para usarmos uma expressão JUEL (muito mais poderosa que FEEL) e deixe o seu input como abaixo.
Basicamente essa expressão verifica se o email de cadastro do usuário é do Gmail (contains). Quando o usuário chegar nesta etapa, ele vai passar como input seu e-mail, que se for um Gmail, vai passar true (definimos como boolean, lembra?) para DMN, caso contrário false.
Logo, agora precisamos definir que nosso Output é uma variável approved (boolean) e de apenas duas linhas na DMN para tratar esses dois cenários possíveis, como abaixo.
Faça deploy desta DMN e mande o POSTMAN disparar uma nova instância de processo no Rest Engine do Camunda para ver o que acontece com nossa instância. Sugiro que adicione um novo Gateway no final, para dar destinos diferentes conforme o usuário for approved ou não (ignore a tosquice do exemplo, tenho certeza que você consegue imaginar cenários práticos mais úteis) , como abaixo.
Para saber se a sua instância finalizou com aprovada ou não, você pode usar a própria API REST do Camunda para consultar o histórico de instâncias finalizadas através do endpoint http://localhost:8080/engine-rest/history/activity-instance/?processInstanceId=x onde x é o id da sua instância (tire a variável e ele irá trazer todas). Também é possível ter informações das decisões tomadas pela DMN Table na aba Decisions do Cockpit e essa é uma das diferenças da versão enterprise (paga) do Camunda, que possui um history visual bem útil.
Como você pode ter percebido, o que fazemos com DMNs pode ser feito também como BPMN, mas abordagens usando Gateways tornam-se muito mais confusas e geram diagramas enormes conforme a complexidade da tomada de decisão cresce. Se você tem muitos desvios condicionais aninhados, trocá-los por uma Business Rule Task atrelada a uma DMN pode ser uma boa opção.
Dica: o pessoal do Camunda disponibiliza um DMN Simulator online, para facilitar os testes de DMNs sem precisar fazer deploy, MAS ele é bem limitado pois apenas interpreta FEEL (JUEL é muito melhor).
Neste tutorial não usamos Node.js, mas ele é uma poderosa tecnologia (assim como Java) para usar com Camunda. Para saber mais sobre Node, confira o meu curso online (banner abaixo).
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.