Chamar dinamicamente uma orchestration com shape “Call Orchestration” - Parte 2
Há algum tempo atrás apresentei aqui, no blog, uma solução para evitarmos a dependência entre orchestration ao utilizar o shape “Call Orchestration”.
O artigo pode ser lido em: http://biztalkbrasil.blogspot.com/2009/10/chamar-dinamicamente-uma-orchestration.html.
Pois bem. Qual não foi minha surpresa ao utilizar o código disponibilizado pelo Jon Facey, e me deparar com um erro, toda vez que a orchestration chamada, ficava com o status dehydrate.
Segue o erro:
“DehydrationFailedException Type 'System.Xml.XmlDocument' in Assembly 'System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.”
Então percebi que se na orchestration chamada houvesse uma porta de uma única direção (request) a solução funcionava bem. Mas se houvesse uma porta de direção dupla (Request/Response), a orchestration ao mudar seu status para dehydrate o exception era acionado.
Para resolver criei outra solução, baseado na idéia do Jon mas com diferenças significativas:
- Agora temos a parte gráfica e podemos debugar a "DLL", como se realmente fosse uma orchestration.
- Criei 3 parâmetros: 1 string de entrada TipoProcesso, que representa o Assembly a ser passado; MsgIn parâmetro de entrada do Tipo XMLDocument; MsgOut parametro de saida do tipo XMLDocument.
- Com esses novos parâmetros a orchestration que será chamada deverá obrigatoriamente conter o parâmetro de entrada do tipo XMLDocument e parâmetro de Saída do tipo XMLDocument.
Por favor, postem um comentário, caso tenham algum outro problema com a DLL.
Disponibilizei um novo release do projeto. Segue o link.
Trabalhando com Biztalk, Sql Adapter e Envelope
Preparando o Sql Server 2005
1: CREATE TABLE [dbo].[Cliente](
3: [Id] [int] IDENTITY(1,1) NOT NULL,
4:
5: [Nome] [varchar](50) NULL,
6:
7: [Profissao] [varchar](20) NULL,
8:
9: [Status] [smallint] NULL,
10:
11: CONSTRAINT [PK_Cliente] PRIMARY KEY CLUSTERED
12:
13: (
14:
15: [Id] ASC
16:
17: )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
18:
19: ) ON [PRIMARY]
20:
21: GO
22:
23: SET ANSI_PADDING OFF
Criaremos também uma Stored Procedure sp_ConsultaCliente:
1: CREATE PROCEDURE [dbo].[sp_ConsultaCliente]
2:
3: AS
4:
5: BEGIN
6:
7: SELECT Id, Nome, Profissao from Cliente
8:
9: WHERE Status = 0 for xml auto, xmldata
10:
11: UPDATE Cliente SET Status = 1
12:
13: END
Crie um novo Biztalk Project chamado SampleEnvelope.
Para gerar schemas a partir do SQL Adapter
1. Clique com botão direito em cima do projeto e em “Add” -> “Add Generated Items”2. Escolha a opção “Add Adapter Metadata” e clique em “Add”.
3. Escolha “SQL” e clique em “Next”;
4. Clique em Set para preencher a Conection String do Banco.
5. Clique em OK e em Next.
6. Preencha o target namespace com http://SampleEnvelope e o Document Root com “ConsultaCliente”. Deixe a opção como Receive Port.

7. Clique em “Next”, Selecione “Stored Procedure” e clique em “Next” novamente.
8. Selecione a Stored Procedure “sp_ConsultaCliente” e clique em “Generate”.

9. Clique mais uma vez em “Next” e depois em “Finish”.

10. Depois de gerado o schema, altere a Stored Procedure:
1: ALTER PROCEDURE [dbo].[sp_ConsultaCliente]
2: AS
3: BEGIN
4: SELECT Id, Nome, Profissao from Cliente
5: WHERE Status = 0 for xml auto
6: UPDATE Cliente SET Status = 1
7: END
8:
Para criar o Envelope Schema
1. Com o botão direito, clique em “Add” -> “New Item”.2. Escolha a opção Schema Files no painel esquerdo.
3. Clique na opção Schema no painel direito.
4. Renomeie o novo schema como schEnvCliente.xsd e clique em Add.

Alterando as propriedades do Envelope schEnvCliente.xsd

Alterar o schema SqlService.xsd para trabalhar com único registro.
1. Abra o schema SqlService.xsd.
2. Clique no nó Cliente e delete os valores nas propriedades “Max Occurs” e “Min Occurs”. Isso fará com que o nó só aceite um registro por vez.
3. Arraste o nó Cliente para o nó <Schema> , colocando-o no mesmo nível que ConsultaCliente.
4. Delete o nó ConsultaCliente.
Deverá ficar parecido com a figura abaixo.

Os Schemas estão configurados, será necessário criar um Receive Pipeline, para ligar o Envelope com o schema normal.
Para criar o Receive Pipeline

O Projeto está pronto. Clique em Build e Deploy. (Não esqueça de setar as propriedades “Application Name” e “Assembly Key File”).
Para Configurar a Receive Port

10. Altere o Receive Pipeline para rcvSampleEnvelope, aquele que foi criado no projeto.
11. Clique em Ok nas duas telas seguintes para concluir.

Para Configurar a Send Port

Executar BRE com código .NET
BRE - Business Rules Engine, ferramenta poderosa onde podemos colocar as regras de negócio da nossa aplicação. Quando essas regras são alteradas, é fácil e simples atualizá-las no BRE sem precisar compilar e publicar novamente o projeto.
Dentro da orchestration podemos executar a policy através do shape “Call Rulles”, mas como executar em uma dll, um componente customizado?
Segue o exemplo em C#:
Observações:
1 – A string que esta sendo passada como parâmetro no Construtor da policy ("DYNAMIC_INVOCATION") é o nome da policy criada no BRE que deve estar com o status de deploy.
2 – O primeiro parâmetro da classe TypedXmlDocument, deve ser o mesmo nome do schema que está publicado no Biztalk Administration Console, no exemplo "BZT_DYNAMIC_INVOCATION.schRetAssemblyOrch"
Espero que possa ser útil!
Trabalhando com Functoid “Table Looping”
Usado em conjunto com o Functoid “Table Extractor”, serve para criar estruturas de any registros podendo conter valores de campos, valores constantes, e valores que resultam de outros functoids. Pode ser usado também para adicionar registros em uma estrutura quando não houver registros de entrada.
Vamos começar com um exemplo bem simples:
- Crie um novo projeto Biztalk.
- Adicione um schema, schInput.
- Para esse schema adicione um Element Field chamado Nome.
- Adicione outro schema, schOutput
- Para esse schema adicione um Record “Cliente”.
- Nesse Record set a propriedade “Max Occurs” para “unbounded”.
- Adicione três Element Field: Nome, Endereco, Cidade.
- Adicione um map, tfmOutput, e referencie os devidos schemas.
Deverá ficar parecido com a seguinte tela:
- Na paleta de Toolbox que fica ao lado esquerdo, expanda a aba “Advanced Functoids” clique e arraste o functoid “Table Looping” para o Grid.
- Com o botão esquerdo do mouse de dois clique para abrir o functoid.
- Clique no botão “Insert New Parameter”.
- O Primeiro parâmetro deve conter o numero de registros que será gerado. Ou o link que corresponde a quantidade de registros.
- O Segundo parametro deve conter o numero de colunas.
- E os demais parâmetros são os possíveis valores.
- No nosso exemplo o Primeiro parâmetro deve conter o valor 4 (haverá 4 registros), e o segundo parâmetro o valor 3 (3 colunas correspondendo Nome, Endereco e Cidade).
- Acrescente também mais 12 parametros, sendo 4 valores para Nome, 4 Valores para Endereço e 4 Valores para Cidade.
- Clique no botão Ok para finalizar.
- Clique com o botão direito no Table Looping e escolha a opção “Configure Table Looping Grid”. Abrirá a seguinte tela:
A Column 1, Column 2 e Column 3 representará o campo Nome, Endereco e Cidade respectivamente.
- Clique em Ok para finalizar.
- Na paleta de Toobox clique e arraste para o grid 3 Table Extrator.
- Clique no Table Looping e arraste ate o Table Extrator.
- Clique duas vezes em cima de cada Table Extrator e acrescente o parâmetro correspondente a coluna. O Primeiro Table Extrator será a coluna 1, o Segundo será a coluna 2 e o Terceiro a coluna 3.
- Clique em cima do Table Extrator e Arraste para o campo Correspondente.
- Clique em cima do Table Looping e arraste para o Record Cliente.
Agora é só clicar em cima do map tfmOutput.btm com o botão direito e clicar em Test Map. Será gerado um XML com o resultado do map. Que deve ser:
Segue o Código do Exemplo.
http://sampletablelooping.codeplex.com/
Nessa solution tem dois projetos, um deles é idêntico ao que acabamos de criar, e o outro é um pouco mais complexo, sendo que a mensagem de entrada parte de um XML.
Até a próxima!


