Pular para o conteúdo
Kitegra
← Voltar ao blog

Módulo deste artigo: Integration Flow Helper

Expressões Camel Simple no SAP CPI: headers, propriedades e ${…} com exemplos

Como funcionam as expressões Camel Simple no SAP CPI: ${header.x}, ${property.x}, ${in.body}, datas, a ordem do Content Modifier, condições de Router e os erros que não retornam nada.

Expressões Camel Simple no SAP CPI: headers, propriedades e ${…} com exemplos

Quase todo valor dinâmico em um iFlow do SAP Cloud Integration (SAP CPI) é escrito em Simple, a linguagem de expressões do Apache Camel: um header no endereço de um receptor, uma propriedade em um Content Modifier, uma data em um nome de arquivo, uma condição em um Router. A sintaxe é curta, ${…}, e é fácil errar um detalhe sem perceber.

Este artigo mostra as expressões que você vai usar todo dia, a ordem em que um Content Modifier as avalia, a diferença entre headers e exchange properties, e os erros que fazem uma expressão não retornar nada, sem nenhum aviso.

O que é uma expressão Simple no SAP CPI

O SAP Integration Suite executa cada iFlow sobre o Apache Camel. Quando um passo é executado, o Camel substitui cada ${…} do campo por um valor da mensagem atual: um header, uma exchange property, o corpo ou uma função embutida, como a data atual. O texto ao redor da expressão fica como está, então Order-${header.orderId}.xml vira Order-4711.xml.

Você pode escrever expressões Simple nos valores do tipo Expression de um Content Modifier e no corpo da mensagem, nos campos de endereço e de consulta de muitos adaptadores receptores, nas condições do tipo Non-XML de Router e Filter, e em campos como o assunto de um e-mail ou o nome de um arquivo SFTP. Os parâmetros externalizados parecem iguais, mas são outra coisa: {{receiverHost}} é substituído uma única vez, quando você implanta o iFlow, enquanto ${…} é avaliado para cada mensagem.

As expressões que você vai usar todo dia

Um punhado de expressões cobre a maioria dos iFlows, e elas se misturam livremente com texto. O corpo de um Content Modifier, por exemplo, pode montar um documento XML inteiro a partir de headers, propriedades e funções:

<Order>
  <Id>${property.orderId}</Id>
  <Customer>${header.customerId}</Customer>
  <ReceivedOn>${date:now:yyyy-MM-dd}</ReceivedOn>
  <Flow>${camelId}</Flow>
  <MessageLog>${property.SAP_MessageProcessingLogID}</MessageLog>
</Order>
ExpressãoO que retorna
${header.orderId}O header da mensagem orderId
${property.orderId}A exchange property orderId (o Camel também aceita ${exchangeProperty.orderId})
${in.body} ou ${body}O corpo atual da mensagem como texto
${date:now:yyyy-MM-dd}A data de hoje no padrão de data Java informado
${camelId}O nome do integration flow em execução
${property.SAP_MessageProcessingLogID}O ID do log de processamento da mensagem atual
${header.CamelHttpResponseCode}O código de status retornado pela última chamada HTTP

Como um Content Modifier avalia headers, propriedades e o corpo

Um Content Modifier percorre suas abas em uma ordem fixa: primeiro a tabela Message Header, depois a tabela Exchange Property e, por fim, o Message Body. Dentro de cada tabela, as linhas são processadas de cima para baixo.

Essa ordem define o que uma expressão consegue ver. Uma linha de propriedade pode ler um header criado antes no mesmo Content Modifier, e o corpo pode usar os dois. Uma linha de header não consegue ler uma propriedade criada pelo mesmo Content Modifier, porque a propriedade ainda não existe quando o header é avaliado; ela lê um valor vazio. Quando precisar disso, defina a propriedade em um Content Modifier anterior ou passe o valor para a tabela de headers, que vem antes.

  • Tipo de origem Expression: o valor é uma expressão Simple, por exemplo ${date:now:yyyyMMdd}-${header.orderId}.
  • Tipo de origem Header ou Property: copia outro header ou outra propriedade pelo nome, sem ${…} em volta.
  • Tipo de origem XPath: lê um valor de um corpo XML (veja o artigo sobre XPath indicado mais abaixo).
  • Os tipos de origem Constant, Local Variable, Global Variable e Number Range cobrem valores fixos e valores armazenados.

Header ou exchange property: qual usar

Um header viaja com a mensagem. Os adaptadores receptores podem repassar headers ao sistema chamado, e os headers atravessam uma chamada ProcessDirect para outro iFlow. Uma exchange property fica dentro do exchange do iFlow atual e nunca é enviada sozinha a um receptor.

Dois detalhes causam a maioria das surpresas. Nomes de header não diferenciam maiúsculas de minúsculas, então ${header.OrderID} e ${header.orderid} leem o mesmo header. Nomes de exchange property diferenciam, então ${property.OrderID} e ${property.orderId} são duas propriedades diferentes, e a segunda pode simplesmente não existir.

  • Use uma propriedade para valores de que só este iFlow precisa: IDs, contadores, flags, cópias salvas do payload.
  • Use um header para valores que um adaptador ou o próximo iFlow precisa receber, e remova os headers que não devem sair do tenant.
  • Não coloque valores grandes em headers: eles viajam em toda chamada.

Condições Simple em Router e Filter

Em uma rota de Router ou em um Filter do tipo Non-XML, a condição é uma expressão Simple comparada com um valor. Os operadores usuais são =, !=, >, >=, <, <=, contains, in e regex, combinados com and ou or. Valores de texto vão entre aspas simples:

${header.orderType} = 'EXPRESS'
${property.amount} > 1000 and ${header.country} in 'DE,AT,CH'
${header.CamelHttpResponseCode} != '200'

Se o header ou a propriedade de uma condição não existir, a condição simplesmente é falsa e a mensagem segue outra rota, muitas vezes a padrão. O artigo sobre headers e propriedades desconhecidos mostra como detectar isso antes que chegue à produção.

Como o Kitegra ajuda

O Kitegra é uma extensão de navegador para o designer do SAP Integration Suite. Digite ${ ou $ em um campo do designer e ele lista os nomes que fazem sentido naquele ponto do iFlow: headers e propriedades definidos em Content Modifiers, em scripts Groovy e JavaScript e em outros pontos do iFlow, headers e expressões padrão do SAP e do Camel, parâmetros {{…}}, variáveis e nomes de Data Store. Um nome definido só em alguns caminhos aparece marcado como “Definido apenas em alguns caminhos”.

O painel de lint aponta um ${ não fechado, espaços sobrando dentro de uma expressão, e headers ou propriedades que nada no iFlow define. Para linhas XPath, um payload de exemplo também gera sugestões de caminho, como explica o artigo sobre XPath. A extensão nunca salva, implanta nem edita o conteúdo de um iFlow, e o seu tenant só muda quando você clica em uma de quatro ações nomeadas, que podem ser desativadas.

Para ver os valores que as suas expressões produzem de verdade, rastreie uma mensagem passo a passo e leia os headers e as propriedades antes de cada passo.

Sem uma conta Kitegra, ela funciona em 5 iFlows por módulo. O plano Free cobre 50, o Starter 100 e o Pro 300. Nos planos de equipe, cada membro tem o Pro, com 300 iFlows por módulo no Startup Team e sem limite no Growth Team e no Scale Team. Enquanto o Kitegra é lançado, todas as ferramentas ficam liberadas para todos que entrarem, inclusive no plano Free. Compare os planos.

Experimente no seu próximo iFlow

Veja o que o Kitegra faz no designer do SAP Integration Suite, ou confira-o ao lado das outras extensões do Chrome da Kitegra.

Perguntas frequentes

Qual é a diferença entre ${header.x} e ${property.x} no SAP CPI?

${header.x} lê um header da mensagem, que viaja com ela e pode chegar a receptores e a outros iFlows. ${property.x} lê uma exchange property, que fica dentro do iFlow atual.

Nomes de header e de propriedade diferenciam maiúsculas de minúsculas?

Os de header não: ${header.OrderID} e ${header.orderid} leem o mesmo header. Os de exchange property sim, então ${property.OrderID} e ${property.orderId} são propriedades diferentes.

Por que meu header fica vazio quando o defino a partir de uma propriedade no mesmo Content Modifier?

Um Content Modifier avalia primeiro a tabela de headers, depois a de propriedades e, por fim, o corpo. Um header não consegue ler uma propriedade criada no mesmo passo; defina a propriedade em um passo anterior.

Como coloco a data de hoje em um nome de arquivo ou em um campo?

Use ${date:now:yyyy-MM-dd} com qualquer padrão de data Java, por exemplo ${date:now:yyyyMMddHHmmss} para um timestamp.

{{parameter}} é uma expressão Simple?

Não. {{…}} marca um parâmetro externalizado, substituído uma única vez quando o iFlow é implantado. ${…} é avaliado pelo Camel para cada mensagem.

O que acontece se uma expressão citar um header que não existe?

Ela retorna um valor vazio sem erro, então o problema aparece mais tarde como uma rota errada ou um campo vazio. Uma verificação de lint ou um passo de proteção detecta isso antes.

Trabalhe em iFlows sem sair do designer

Adicione o Kitegra ao Chrome ou ao Microsoft Edge. Comece grátis, sem precisar de conta.