Monday, December 12, 2005

BizTalk 2004: Message Brokers com Orquestrações


O Message Broker é um padrão de desenho conhecido, e que tem uma implementação simples com BizTalk 2004. Esta implementação baseia-se totalmente nos mecanismos de Messaging do BizTalk: as mensagens entram por Receive Locations/Receive Ports, e existe um conjunto de Send Ports com subscrições com diferentes filtros, que encaminham as mensagens para diferentes destinos conforme as suas características/conteúdos. O mecanismo é simples, como referi, mas também um pouco limitado, porque só pode ter lógica implementada ao nível de componentes de messaging como os pipelines.



 


Assim, numa primeira abordagem, quis implementar um broker, mas colocando no meio, entre a recepção da mensagem/pedido e o envio para o seu receptor final, uma componente de orquestração. Criei uma orquestração que é activada pela recepção de uma mensagem num Web Service, faz algum logging, e depois publica essa mesma a mensagem de saída de volta para a Message Box, de onde será enviada para o seu destino pelos mesmos Send Ports da primeira solução.
O pormenor desta implementação é que para se publicar para a Message Box sem ter associado um Send Port, se deve obviamente usar o Direct Binding.
Adicionalmente, deve seleccionar-se a opção que indica que “Routing between ports will be defined by filter expressions on incoming messages in the Message Box database”.
Finalmente, os filtros que haviam sido definidos para o primeiro cenário podem ainda ser utilizados, mas é necessário alterar as condições de forma a deixarem de testar o ReceivedPortName, vão basear-se apenas nas características das próprias mensagens (o que, por agora, é aceitável).


 


Esta solução funciona, mas o meu objectivo era ter um broker entre orquestrações: um componente que receba uma mensagem M, faça alguma coisa com ela, e publique M1 (uma nova mensagem, baseada em M com poucas alterações) de volta para a MsgBox, onde seja consumida por uma de N sub-orquestrações consumidoras. A solução é, no imediato, simples: basta criar as tais N sub-orquestrações, e para cada uma delas especificar no Receive Port que as activa que o Port Binding é Direct com a opção "Routing between ports will be defined by filter expressions on incoming messages in the Message Box database" selecccionada. De seguida, criei filtros distintos nas Shapes de Receive para cada uma das sub-orquestrações (por exemplo, no orquestração "ProcessaSalarios" coloquei "Estado == ProcessarSalarios", em "ProcessaFerias" coloquei "Estado == ProcessarFerias", etc.).


 


Esta solução funcionou nos testes que efectuei, mas tem um problema: quando alguma destas orquestrações envia uma mensagem M2 para um Send Port (por exemplo, para debug), se os filtros estiverem como descrevi acima e não tivermos alterado o campo Estado que referi no exemplo, o BizTalk vai entrar em loop: M2 é gravado na MsgBox, sendo enviado para o Send Port e igualmente de novo para a orquestração que processou o M1 correspondente. Nada conveniente, um ciclo infinito no BizTalk.


 


Como resolver? Por exemplo, adicionando condições aos filtros das sub-orquestrações. O problema é que, por se usar Direct Binding, muito poucas propriedades da mensagem M1 são publicadas no contexto de M2 (como se pode comprovar na coluna IsPromoted das Context Properties no HAT), logo não existem valores interessantes com que se possam fazer filtros.


 


Para resolver isto, optei por adicionar ao Property Schema que já tinha, com as propriedades promovidas do schema de M/M1/M2, uma nova propriedade, a que chamei "IsFromBroker" (obrigado aqui ao Pedro Teixeira da MS pela dica). Esta propriedade, ao editar o Property Schema, tem de ter o atributo "Property Schema Base" com o valor "MessageContextPropertyBase" , uma vez que não se trata de um valor obtido do conteúdo da mensagem.


Atribuí depois a esta property o valor True no Broker, e a False em cada uma das "sub-orquestrações" que enviam M2:


 


theBrokerRequestMsg(theNamespace.IsFromBroker) = true; // ou false


 


Adicionei também aos filtros das sub-orquestrações a condição "IsFromBroker == true".


 


Finalmente, resta o problema de esta nova propriedade não ser passada para a MsgBox com o Direct Binding. O truque aqui está em recorrer à correlação: criei um Correlation Type apenas com o IsFromBroker (mas podia ter também qualquer outra propriedade de que se queira forçar a promoção), e um Correlation Set com base neste tipo, que usei no Send Port do Broker (coloquei-o como Initializing Correlation Set). Note-se que aqui não se está a usar o mecanismo de Correlation por si, mas apenas como uma forma de forçar o BizTalk a promover propriedades que normalmente não o seriam, devido à utilização do Direct Binding


Ao que parece, no BizTalk Server 2006 já não é necessário recorrer a este expediente.


 


E voilá! Mais complexo de explicar do que fazer. :-)


 


Para mais informações sobre este tema, recomendo dois artigos do blog do Charles Young, sobre Direct Binding e Flexible Correlation, que complementam muito bem a documentação do produto.


Finalmente, uma chamada de atenção: no livro "BizTalk Server 2004 Unleashed", página 363 sobre "Direct Port Binding Between Orchestrations", diz-se que: "Direct binding bypasses the messaging system. Messages that use this technique remain withing the orquestration engine." Estas afirmações estão incorrectas, como a primeira abordagem ao broker com orquestrações demonstra. Aliás, segundo o primeiro dos dois artigos que referi, a única coisa que não passa pela Message Box são as invocações Call Orchestration.


 


jota

?>

No comments:

Post a Comment