Roteamento de mensagens XML por tipo de nó no Jitterbit Studio
Introdução
Quando um único endpoint entrega mais de um tipo de mensagem XML, a integração deve inspecionar a carga útil antes de processá-la. Uma pasta de entrada compartilhada, fila ou endpoint de API pode conter tanto uma atualização de registro quanto um cancelamento de registro, cada uma usando um elemento diferente sob a mesma raiz. A operação que lida com atualizações não pode processar uma mensagem de cancelamento, então a carga útil precisa ser examinada e direcionada para a operação que a corresponde.
Para testar se um nó específico está presente, execute uma consulta XPath contra a carga útil com SelectNodes e conte os resultados com Length. Um resultado vazio significa que o nó está ausente. Você então ramifica com base nesse resultado e chama a operação correspondente com RunOperation.
Este guia usa uma mensagem de pedido como exemplo. Ambos os tipos de mensagem compartilham os mesmos elementos de raiz e corpo, e diferem apenas no elemento diretamente abaixo do corpo:
Create or update message Cancellation message
Envelope Envelope
└── Body └── Body
└── OrderUpdate └── OrderCancellation
└── Order └── Order
Essa estrutura é comum em envelopes de estilo intercâmbio, onde um elemento raiz compartilhado carrega tanto um registro quanto um evento sobre esse registro. O objetivo é detectar qual dos OrderUpdate ou OrderCancellation está presente, e então invocar a operação Inserir ou Atualizar Pedido ou a operação Cancelar Pedido.
Nota
GetNodeName foi projetado para ler o nome de um nó já retornado por uma função como SelectSingleNode, e não para testar diretamente a presença de um nó. Para usá-lo para roteamento, emparelhe-o com SelectSingleNode, conforme mostrado na Opção B abaixo.
Padrão de design
A lógica de roteamento reside em um passo de script em sua própria operação de roteador, a montante das operações que realizam o trabalho:
reads XML] --> B[Script step
router] B --> C[Insert or
Update Order] B --> D[Cancel Order]
A operação do roteador lê a carga útil, determina o tipo de mensagem e chama exatamente uma operação a montante. Cada operação a montante permanece simples, pois só recebe o tipo de mensagem para o qual foi construída.
Passo 1: Ler a carga útil em uma variável
O script do roteador precisa do XML bruto como uma string. Como você obtém isso depende de como a mensagem chega.
-
De um arquivo ou atividade de armazenamento: Use
ReadFilecom um caminho de referência para a atividade de leitura:$gv_payload = ReadFile("<TAG>activity:tempstorage/Inbound XML/tempstorage_read/Read Message</TAG>"); -
De uma API do API Manager: Use a variável
jitterbit.api.request.body, que contém a carga útil enviada:$gv_payload = $jitterbit.api.request.body;
Atribuir a carga útil a uma variável global serve a um segundo propósito. As operações chamadas com RunOperation herdam todas as variáveis globais, de modo que a operação a montante pode ler a mensagem de $gv_payload sem ler a fonte uma segunda vez.
Passo 2: Identificar o namespace
A maioria dos XML de aplicações empresariais possui namespace. Se o elemento raiz da carga útil possui um atributo xmlns, cada elemento no documento pertence a esse namespace, e uma consulta XPath que o omite não corresponde a nada.
Abra uma carga útil de exemplo e observe o elemento raiz:
<Envelope xmlns="http://example.com/schemas/orders">
Copie o URI do namespace. No próximo passo, você declara um prefixo para ele e usa esse prefixo em cada elemento na consulta XPath. SelectNodes aceita essas declarações como argumentos de string adicionais na forma prefix=uri.
Se o elemento raiz não tiver um atributo xmlns, o documento não possui namespace. Omitir as declarações de prefixo e os prefixos nos nomes dos elementos.
Passo 3: Testar se o nó existe
SelectNodes retorna um array de cada nó que a consulta corresponde. Quando nada corresponde, o array está vazio, então Length retorna 0. Comparar essa contagem com zero é o teste de existência:
$gv_updateNodes = SelectNodes($gv_payload,
"/o:Envelope/o:Body/o:OrderUpdate",
"o=http://example.com/schemas/orders");
// True when the payload contains a create or update message
Length($gv_updateNodes) > 0;
Substitua o URI do namespace pelo que está no Passo 2 e substitua os nomes dos elementos pelos que estão no seu próprio payload.
Dica
Consulte o caminho específico em vez do nome do elemento sozinho. Um caminho ancorado na raiz confirma tanto que o elemento está presente quanto que ele aparece onde o esquema espera, o que evita uma correspondência falsa em um elemento com o mesmo nome em outro lugar no documento.
Passo 4: Roteirizar para a operação correspondente
Escolha uma das duas abordagens a seguir. A Opção A é a escolha mais direta para dois tipos de mensagem. A Opção B é a melhor opção para três ou mais, pois executa uma consulta XPath independentemente de quantos tipos de mensagem o endpoint possui.
Opção A: Testar cada tipo de mensagem em sequência
Adicione um passo de script à operação do roteador. O script testa primeiro a mensagem de atualização e recua para a mensagem de cancelamento.
Substitua o caminho de referência da atividade, o URI do namespace, os nomes dos elementos e os dois caminhos de referência da operação pelos valores do seu próprio projeto.
// Read the inbound message
$gv_payload = ReadFile("<TAG>activity:tempstorage/Inbound XML/tempstorage_read/Read Message</TAG>");
// Look for the create or update message: Envelope/Body/OrderUpdate
$gv_updateNodes = SelectNodes($gv_payload,
"/o:Envelope/o:Body/o:OrderUpdate",
"o=http://example.com/schemas/orders");
// Look for the cancellation message: Envelope/Body/OrderCancellation
$gv_cancelNodes = SelectNodes($gv_payload,
"/o:Envelope/o:Body/o:OrderCancellation",
"o=http://example.com/schemas/orders");
If(Length($gv_updateNodes) > 0,
WriteToOperationLog("Routing to insert or update.");
If(!RunOperation("<TAG>operation:Insert or Update Order</TAG>"),
RaiseError(GetLastError())
);
,
If(Length($gv_cancelNodes) > 0,
WriteToOperationLog("Routing to cancellation.");
If(!RunOperation("<TAG>operation:Cancel Order</TAG>"),
RaiseError(GetLastError())
);
,
RaiseError("Unrecognized message type: no OrderUpdate or OrderCancellation node found.")
);
);
Opção B: Ler o tipo de mensagem do corpo
Como ambos os tipos de mensagem ocupam a mesma posição no documento, você pode selecionar qualquer elemento que esteja sob o corpo e ler seu nome, então ramificar com base nesse único valor. SelectSingleNode retorna o primeiro nó correspondente, e GetNodeName retorna seu nome. O * na consulta XPath corresponde a um elemento de qualquer nome, então a consulta não precisa conhecer os tipos de mensagem com antecedência.
Essa abordagem também registra o tipo de mensagem no log da operação em cada execução, o que é útil quando os payloads do endpoint não estão totalmente documentados.
// Read the inbound message
$gv_payload = ReadFile("<TAG>activity:tempstorage/Inbound XML/tempstorage_read/Read Message</TAG>");
// Select whatever element sits directly under Body, then read its name
$gv_bodyChild = SelectSingleNode($gv_payload,
"/o:Envelope/o:Body/*",
"o=http://example.com/schemas/orders");
$gv_messageType = GetNodeName($gv_bodyChild);
WriteToOperationLog("Message type: " + $gv_messageType);
// Route on the message type. Add a branch for each additional type,
// and raise an error on anything unrecognized.
If($gv_messageType == "OrderUpdate",
If(!RunOperation("<TAG>operation:Insert or Update Order</TAG>"),
RaiseError(GetLastError())
);
,
If($gv_messageType == "OrderCancellation",
If(!RunOperation("<TAG>operation:Cancel Order</TAG>"),
RaiseError(GetLastError())
);
,
RaiseError("Unrecognized message type: " + $gv_messageType)
);
);
Um payload cujo elemento de corpo não corresponde a nenhum dos ramos cai no RaiseError final, que também cobre o caso em que o corpo não tem nenhum elemento filho.
Pontos-chave sobre ambos os scripts:
RunOperationretornafalsequando a operação chamada falha. Testar esse valor de retorno e chamarRaiseErrorcomGetLastErrorinterrompe a operação do roteador e aciona sua ação configurada On Fail. Sem esse teste, uma falha na operação a montante deixa o roteador relatando sucesso.- Levantar um erro em um tipo de mensagem não reconhecido revela mudanças de esquema e payloads malformados nos logs de operação em vez de permitir que a mensagem passe sem ser processada.
RunOperationé executado de forma síncrona por padrão, então o roteador aguarda a conclusão da operação a montante. Isso é o que permite ao roteador detectar uma falha a montante. Executar de forma assíncrona retornaria o controle imediatamente e relataria apenas se a operação foi enfileirada.- Operações chamadas com
RunOperationsão encadeadas e executadas no mesmo agente que o roteador. WriteToOperationLogregistra qual ramo foi seguido, o que torna uma mensagem mal roteada fácil de diagnosticar posteriormente.
Etapa 5: Dê às operações a montante sua entrada
Cada operação a montante precisa do payload que o roteador inspecionou. Use qualquer um desses que se encaixe no projeto:
- Leia da variável global. A operação a montante herda
$gv_payloaddo roteador. Mapeie ou script a partir dessa variável diretamente, sem uma segunda leitura da fonte. - Leia a fonte novamente. Se o payload estiver em armazenamento temporário ou em outro local persistente, a operação a montante pode usar sua própria atividade de leitura contra o mesmo local.
Cada operação a montante possui um esquema de origem para um único tipo de mensagem, o que mantém sua transformação simples.
Verifique a integração
-
Prepare um exemplo de carga útil de cada tipo de mensagem, além de uma terceira carga cuja parte do corpo não corresponda a nenhuma.
-
Implante e execute a operação do roteador contra a mensagem de criação ou atualização.
-
Nos logs da operação, confirme que o roteador registrou o caminho de atualização e que a operação
Inserir ou Atualizar Pedidofoi executada. Confirme que a operaçãoCancelar Pedidonão foi executada. -
Execute o roteador contra a mensagem de cancelamento e confirme o oposto: a operação
Cancelar Pedidofoi executada e a operaçãoInserir ou Atualizar Pedidonão foi. -
Execute o roteador contra a carga não reconhecida e confirme que a operação falhou com o erro "Tipo de mensagem não reconhecido" e que nenhuma operação a montante foi executada.
-
Se cada carga útil cair no ramo não reconhecido, o namespace é a primeira coisa a verificar. Confirme que a URI no script corresponde exatamente ao valor
xmlnsno elemento raiz da carga, incluindo qualquer barra final, e que cada elemento na consulta XPath carrega o prefixo declarado. -
Se uma carga útil for direcionada para a operação errada, registre as contagens de nós (Opção A) ou o tipo de mensagem (Opção B) e compare-as com a carga útil de exemplo.
WriteToOperationLog("Nódulos de atualização: " + Length($gv_updateNodes))confirma o que a consulta realmente correspondeu.
Guias relacionadas
- Encadear e controlar operações: Vinculando operações com a ferramenta Invocar Operação ou
RunOperation, incluindo captura de erros. - Gerenciar fluxos de trabalho usando scripts de controle: O padrão mais amplo de script de controle do qual este roteador é uma forma.
- Configurar tratamento de erros em operações: Definindo as ações Em Falha que os chamados
RaiseErrordo roteador acionam. - Filtrar registros usando condições: Ramificação dentro de uma transformação em vez de entre operações.