Rotear 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 o payload antes de processá-lo. Uma pasta de entrada compartilhada, fila ou endpoint de API pode conter tanto uma atualização de registro quanto um cancelamento de registro, cada um usando um elemento diferente sob a mesma raiz. A operação que trata atualizações não pode processar uma mensagem de cancelamento, portanto o payload deve ser examinado e roteado para a operação que corresponde a ele.
Para testar se um nó específico está presente, execute uma consulta XPath contra o payload com SelectNodes e conte os resultados com Length. Um resultado vazio significa que o nó está ausente. Depois você faz uma ramificação 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 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
Esta forma é comum em envelopes no estilo de intercâmbio, onde um elemento raiz compartilhado carrega um registro ou um evento sobre esse registro. O objetivo é detectar qual de OrderUpdate ou OrderCancellation está presente, e então invocar a operação Insert or Update Order ou a operação Cancel Order.
Nota
GetNodeName foi desenvolvida para ler o nome de um nó já retornado por uma função como SelectSingleNode, não para testar a presença de um nó diretamente. Para usá-la no roteamento, combine-a com SelectSingleNode conforme mostrado em Opção B abaixo.
Padrão de design
A lógica de roteamento fica em uma etapa de script em sua própria operação de roteador, a montante das operações que fazem o trabalho:
reads XML] --> B[Script step
router] B --> C[Insert or
Update Order] B --> D[Cancel Order]
A operação de roteador lê o payload, determina o tipo de mensagem e chama exatamente uma operação a jusante. Cada operação a jusante permanece simples, porque recebe apenas o tipo de mensagem para o qual foi construída.
Etapa 1: Ler o payload em uma variável
O script de roteador precisa do XML bruto como uma string. Como você o obtém depende de como a mensagem chega.
-
De uma atividade de arquivo ou 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 o payload enviado:$gv_payload = $jitterbit.api.request.body;
Atribuir o payload a uma variável global serve a um segundo propósito. Operações chamadas com RunOperation herdam todas as variáveis globais, então a operação a jusante pode ler a mensagem de $gv_payload sem ler a fonte uma segunda vez.
Etapa 2: Identificar o namespace
A maioria do XML de aplicações comerciais possui namespace. Se o elemento raiz do payload tiver um atributo xmlns, todos os elementos no documento pertencem a esse namespace, e uma consulta XPath que o omite não encontra nada.
Abra um payload de exemplo e observe o elemento raiz:
<Envelope xmlns="http://example.com/schemas/orders">
Copie o URI do namespace. Na próxima etapa, 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. Omita as declarações de prefixo e os prefixos nos nomes dos elementos.
Etapa 3: Testar se o nó existe
SelectNodes retorna uma matriz de cada nó que a consulta encontra. Quando nada corresponde, a matriz está vazia, 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 por aquele da Etapa 2 e substitua os nomes dos elementos pelos de seu próprio payload.
Dica
Faça consultas para o caminho específico em vez de apenas o nome do elemento. Um caminho ancorado na raiz confirma tanto que o elemento está presente quanto que aparece onde o schema o espera, o que evita uma correspondência falsa em um elemento de mesmo nome em outro lugar do documento.
Etapa 4: Rotear 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 é mais adequada para três ou mais, pois executa uma consulta XPath independentemente de quantos tipos de mensagem o endpoint transporta.
Opção A: Testar cada tipo de mensagem por vez
Adicione uma etapa de script à operação de roteamento. O script testa a mensagem de atualização primeiro 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 de 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, depois ramificar 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 de operações 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 nenhuma das ramificações passa para o RaiseError final, que também cobre o caso em que o corpo não tem elemento filho algum.
Pontos-chave sobre ambos os scripts:
RunOperationretornafalsequando a operação chamada falha. Testar esse valor de retorno e chamarRaiseErrorcomGetLastErrorinterrompe a operação de roteamento e dispara sua ação On Fail configurada. Sem esse teste, uma falha na operação downstream deixa o roteador informando sucesso.- Gerar um erro em um tipo de mensagem não reconhecido evidencia alterações de schema e payloads malformados nos logs de operações em vez de permitir que a mensagem passe sem processamento.
RunOperationé executado sincronamente por padrão, portanto o roteador aguarda a conclusão da operação downstream. Isso é o que permite ao roteador detectar uma falha downstream. A execução assíncrona devolveria o controle imediatamente e informaria apenas se a operação foi enfileirada.- As operações chamadas com
RunOperationsão encadeadas e executadas no mesmo agent que o roteador. WriteToOperationLogregistra qual ramificação foi seguida, o que torna direto diagnosticar uma mensagem roteada incorretamente depois do fato.
Etapa 5: Fornecer entrada às operações downstream
Cada operação downstream precisa do payload que o roteador inspecionou. Use o que se encaixa melhor no projeto:
- Ler da variável global. A operação downstream herda
$gv_payloaddo roteador. Mapeie ou faça script dessa variável diretamente, sem uma segunda leitura da origem. - Ler a origem novamente. Se o payload estiver em armazenamento temporário ou em outro local persistente, a operação downstream pode usar sua própria atividade de leitura contra o mesmo local.
Cada operação downstream tem um esquema de origem para apenas um tipo de mensagem, o que mantém sua transformação simples.
Verificar a integração
-
Prepare um payload de amostra de cada tipo de mensagem, mais um terceiro payload cujo elemento body não corresponda a nenhum deles.
-
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
Insert or Update Orderfoi executada. Confirme que a operaçãoCancel Ordernão foi executada. -
Execute o roteador contra a mensagem de cancelamento e confirme o oposto: a operação
Cancel Orderfoi executada e a operaçãoInsert or Update Ordernão foi. -
Execute o roteador contra o payload não reconhecido e confirme que a operação falhou com o erro "Unrecognized message type" e que nenhuma operação downstream foi executada.
-
Se todo payload cair no branch não reconhecido, o namespace é a primeira coisa a verificar. Confirme que o URI no script corresponde exatamente ao valor
xmlnsno elemento raiz do payload, incluindo qualquer barra à direita, e que cada elemento na consulta XPath tenha o prefixo declarado. -
Se um payload for roteado para a operação errada, registre a contagem de nós (Opção A) ou o tipo de mensagem (Opção B) e compare com o payload de amostra.
WriteToOperationLog("Update nodes: " + Length($gv_updateNodes))confirma o que a consulta realmente correspondeu.
Guias relacionados
- Encadear e controlar operações: Vinculando operações com a ferramenta Invoke Operation ou
RunOperation, incluindo captura de erros. - Gerenciar fluxos de trabalho usando scripts de controlador: O padrão de script de controlador mais amplo do qual este roteador é uma forma.
- Configurar tratamento de erros em operações: Definindo as ações On Fail que as chamadas
RaiseErrordo roteador acionam. - Filtrar registros usando condições: Ramificação dentro de uma transformação em vez de entre operações.