Saturday, December 31, 2005

BizTalk 2004: Identity e Principal

Num projecto em que estou envolvido, existe uma camada de objectos que faz validações de segurança aplicacionais com base num contexto de segurança específico aquando da invocação. Foram definidos assim uma subclasse de GenericIdentity, MyIdentity; e um Principal a acompanhar, MyPrincipal (subclasse de GenericPrincipal). MyIdentity encapsula um conjunto de atributos extra sobre o utilizador actual. A segunda classe, MyPrincipal, limita-se a fornecer um interface strongly-typed sobre a primeira. Ambas as classes estão marcadas como serializáveis.


Já no BizTalk, as orquestrações iniciam-se criando uma instância de MyIdentity, que é preenchida com os tais atributos extra, e de seguida afecta-se a Thread corrente com um MyPrincipal criado com a identidade. Qualquer coisa como:


myIdentity = new MyIdentityNamespace.MyIdentity("jota", "administrator");


System.Threading.Thread.CurrentPrincipal = new MyIdentityNamespace.MyPrincipal (myIdentity);


Independentemente dos méritos da abordagem, levantou-se logo a questão: o BizTalk persiste esta informação quando se dá, por exemplo, uma desidratação numa orquestração?


A documentação do produto diz o seguinte sobre persistência:


The orchestration engine saves to persistent storage the entire state of a running orchestration instance at various points, so that the instance can later be completely restored in memory. The state includes:



  • The internal state of the engine, including its current progress.
  • The state of any .NET components that maintain state information and are being used by the orchestration.
  • Message and variable values.

A resposta, apesar do que possa eventualmente dar a entender o texto acima, é: não. Fiz uma pequena orquestração para testar esta situação, causando uma desidratação, e se até ela acontecer o MyPrincipal criado parecia estar na CurrentThread, tal como afectado, depois da desidratação já não estava lá. Coisas da vida. :-)


jota

Thursday, December 22, 2005

BizTalk 2004: às voltas com o Direct Binding

Quando uma mensagem é colocada na Message Box, e não existe nenhuma subscrição que a apanhe, são gerados tipicamente três (ou mais) erros no Event Log indicando a condição, como este:


The Messaging engine failed to process a message submitted by adapter:SOAP Source URL:/MyVD/MyWS.asmx. Details:Could not find a matching subscription for the message. This error occurs if the subscribed orchestration schedule or send port has not been started, or if some of the message properties necessary for subscription evaluation have not been promoted.


Este é possivelmente o erro mais frequente em desenvolvimento com BizTalk 2004, e geralmente é seguido da utilização do BtsSubscriptionViewer, incluido no SDK, para confirmar que subscrições existem realmente.


Quando se utiliza Direct Binding, no entanto, o que sucede não é bem isto. Como referi num post anterior, ao contrário do que a própria documentação pode deixar a entender, as mensagens enviadas com Direct Binding, apesar de parecerem invocações directas (síncronas) de orquestrações, passam pela Message Box. O que sucede então se uma orquestração publicar uma mensagem com Direct Binding e não existir nenhuma subscrição?


De forma semelhante ao primeiro cenário, vamos ter um erro no Event Log:


Microsoft.XLANGs.Core.PersistenceException: Exception occurred when persisting state to the database. ---> Microsoft.BizTalk.XLANGs.BTXEngine.PersistenceItemException: A batch item failed persistence Item-ID 77c8fa0a-d202-42c6-9ed8-49e3abfdd9db OperationType MAIO_CommitBatch Status -1061151998 ErrorInfo The published message could not be routed because no subscribers were found.


Ao contrário do que sucede no caso mais comum, no entanto, este erro corresponde a uma excepção que é gerada aquando do Send, na orquestração que faz o envio com Direct Binding, e não pelo motor do BizTalk ao avaliar as subscrições. As subscrições parecem ser avaliadas síncronamente, e a mensagem não chega a ser guardada na Message Box.


E não acaba aqui: se a orquestração for transacional (tipicamente, Long Running), o mecanismo de Compensação vai ser desencadeado, para reverter as acções eventualmente já realizadas. Se isto não for o pretentido, basta colocar o Send dentro de um novo Scope transacional Long Running, e adicionar um Exception Handler. Agora ficamos sem erro no Event Log, e podemos tratar a situação como pretendermos.


Pode não parecer, mas o BizTalk tem muita piada. :-)


jota

Monday, December 19, 2005

BizTalk 2004: Tool para remover policies/vocabulários

Tenho estado a utilizar a framework de deployments do Scott Colestock/TraceOfThought para BizTalk 2004, mas esta tem uma pequena limitação, o facto de não permitir a remoção de policies ou vocabulários, apenas o seu "undeployment". Para resolver, fiz uma pequena aplicação consola que remove policies/vocabulários, e que se pode usar em scripts durante o desenvolvimento.


Se alguém estiver interessado, o zip com a solução está aqui (para VS2003). Uso a aplicação incluída na framework do Scott para fazer o deployment, e a minha para fazer o undeploy/remoção.


 

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

?>

Tuesday, December 6, 2005

DSL Tools para versão final do VS2005

Saiu mais uma build das DSL Tools (Novembro 2005), desta vez já com suporte para a versão definitiva do VS2005, um pouco mais tarde que o WCF e WWF. Além de melhorias de qualidade e desempenho (o que me deixa muito contente), parece que há duas novas funcionalidades significativas: validação de modelos (que vem acompanhado de um novo walkthough) e deployment de editores com MSIs. Inclui-se também um guia para fazer a actualização da versão de Setembro para esta.


Ainda não há nova versão do "DSL Dm -> Dd", não deve tardar. E o SDK do VS2005, um requisito das DSL Tools, está aqui.


jota