Neste post vou mostrar como criar, registrar e usar funções XPath personalizadas em expressões XQuery no Oracle Service Bus. Atualmente estou trabalhando com a versão 12.2.1.0.0 do produto, logo as implementações descritas abaixo foram implementadas e testadas nesta versão do OSB e a IDE JDeveloper.

A implementação do Oracle Service Bus fornece uma estrutura extensível para criação de funções XPath personalizadas para usarmos em expressões XQuery em fluxos de mensagens Proxy, Split-Joins e XQuery Mapper.

Os passos para criar e usar funções XPath personalizadas basicamente se da em 3 etapas:

  1. Criar e Empacotar classes Java com as funções personalizadas;
  2. Registro de funções;
  3. Usar as funções personalizadas;

IMPORTANTE: A Oracle recomenda que não criamos funções personalizadas que tenham efeitos colaterais e alterações de estado em outro recurso; Por exemplo: Atualizar uma tabela de banco de dados ou participar de transações globais. Devemos apenas criar funções que contribuam apenas para o resultado de funções XQuery. Se for necessário realizar operações que altere estado ou possa gerar efeitos colaterais com outros recursos, use o mecanismo específico para sua tarefa, como por exemplo Java Callouts.

Criar e Empacotar classes Java com as funções personalizadas

A a criacão da classe e seus método possuem diretrizes:

  • Classe – A classe deve ser pública.
  • Método – O método deve ser público e estático.

Aqui a classe e método criado para exemplo:

package br.com.parmigiani.lab;

/**
 * @author Ednei Parmigiani
 * Classe com funções personalizadas para utilização em XPath no Oracle Service Bus
 */
public class CustomXPathFunctions {

	/**
	 * Método retorna mensagem de boas-vindas
	 * @param name Nome do usuário
	 * @return {@link String}
	 */
	public static String welcomeMessage(String name) {
		return String.format("Welcome %s to the world of custom XPath functions", name);
	}
}

Os tipos suportados pelos argumentos e valores de retorno dos métodos estão na listagem abaixo. Se um tipo não estiver listado, ele não é suportado. As classes internas e os arrays multidimensionais não são suportados.

Tipo de Java XQuery Type Tipo XSLT
Java.lang.String xs:string string
int, java.lang.Integer xs:int number
boolean, java.lang.Boolean xs:boolean boolean
long, java.lang.Long xs:long number
short, java.lang.Short xs:short number
byte, java.lang.Byte xs:byte number
double, java.lang.Double xs:double number
float, java.lang.Float xs:float number
char, java.lang.Char xs:string object
java.math.BigInteger xs:integer number
java.math.BigDecimal xs:decimal number
Java.util.Date xs:datetime Ver obs 1
java.sql.Date xs:data Ver obs 1
java.sql.Time xs:time Ver obs 1
javax.xml.namespace.QName xs:Qname Ver obs 1
org.apache.xmlbeans.XmlObject element() Ver obs 1
org.w3c.dom.Element element() O tipo de conjunto de nós XSLT não é suportado com funções XPath personalizadas.

Obs1. É convertido para uma string, depois volta como o tipo original.

Gere um arquivo JAR a partir do seu projeto Java que contém a classe com as funções que deseja disponibilizar e guarde para usamos no passo “3. Usar as funções personalizadas”.

Registro de funções

Quando registramos funcões no OSB estas ficam disponíveis para todos os projetos e serviços do barramento de uma instalação. Não conseguimos restringir um conjunto de funções por domínios específicos. Registrar uma função personalizada envolve a criação de um arquivo XML, é através deste arquivo que o OSB identifica e fornece na estrutura de funções do produto as operações para usarmos os recursos.

Temos um conjunto de elementos que compõe o arquivo de registro, abaixo segue a Estrutura e Definição:

category id
    group id
        function
            name
            comment
            namespaceURI
            className
            method
            isDeterministic

Definição dos elementos:

  • category id – Identificador do grupo que centraliza fisicamente um conjunto de funções. Por exemplo, “Parmigiani Bus XFunctions :)”.
  • group id – Um elemento opcional. Para identificar um subcategoria de funções. As diretrizes de nomeação para identificação de categoria se aplicam ao ID do grupo.
  • name – O Nome da função que vai aparecer nas expressões XQuery.
  • comment – Comentário descritivo da função. Embora esta descrição não apareça na interface do usuário, é interessante fornecer orientação que explique como usar, utilizar e qual o comportamento da função.
  • namespaceURI – Uma URI como identificador da função. Os namespaces personalizados que você fornece aparecem na lista de namespaces padrão do Oracle Service Bus no editor XQuery.
  • className – O caminho absoluto da classe Java personalizada de função.
  • method – O método Java personalizado que implementa a função, precedido pelo tipo de retorno. Por exemplo: int getAge(Java.util.Date).
  • isDeterministic – Valor true ou false declarando se a função é ou não determinista. Uma função deterministas sempre fornecem os mesmos resultados; por exemplo, uma função que concatena Strings. As funções não-deterministas retornam resultados únicos; Por exemplo, uma função que retorna a hora do dia. Embora você possa usar funções não deterministas, o padrão XQuery recomenda que as funções sejam deterministas para garantir a otimização do mecanismo XQuery.
  • scope – Aqui o escopo em que a funções será utilizada no Barramento.

Agora que sabemos as diretrizes que as classes e seus métodos devem possuir, e conhecemos os elementos de definição para registro da XPath personalizada, vamos criar o arquivo XML para registrar a função “welcomeMessage” disponível na classe “CustomXPathFunctions” criada na sessão 1. Criar e Empacotar a classe Java com as funções personalizadas; Crie um arquivo XML com o conteúdo abaixo e salve com o nome MyCustom-xquery.xml

<?xml version="1.0" encoding="UTF-8"?>
<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
	<xpf:category id="Parmigiani Labs XFunctions">
		<xpf:function>
			<xpf:name>welcomeMessage</xpf:name>
			<xpf:comment>Retorna mensagem de boas-vindas para o usuário.</xpf:comment>
			<xpf:namespaceURI>http://www.parmigiani.com.br/lab/custom/osb/xpath</xpf:namespaceURI>
			<xpf:className>br.com.parmigiani.lab.CustomXPathFunctions</xpf:className>
			<xpf:method>java.lang.String welcomeMessage(java.lang.String)</xpf:method>
			<xpf:isDeterministic>false</xpf:isDeterministic>
			<xpf:scope>Pipeline</xpf:scope>
			<xpf:scope>SplitJoin</xpf:scope>
		</xpf:function>
	</xpf:category>
</xpf:xpathFunctions>

IMPORTANTE: Certifique-se de referenciar corretamente sua classe e método no arquivo XML de registro;

Usar as funcões personalizadas
Na versão 12c do Oracle Fusion Middleware conseguimos criar nossos projetos OSB na IDE JDeveloper e vou mostrar como as nossa funções personalizada vai aparecer na IDE.

Agora, copie o arquivo JAR criado no passo “1. Criar e Empacotar a classe Java com as funções personalizadas” e o arquivo MyCustom-xquery.xml criado no passo “2. Registro de funções” no diretório: OSB_ORACLE_HOME/config/xpath-functions/

Na inicialização do ambiente, o Oracle Service Bus procura classes de funções personalizadas neste diretório e as carrega para utilização. Lembre-se de baixar o ambiente e fechar a IDE JDeveloper, copiar os arquivos e subir o ambiente e a IDE para que nossa função seja carregada e fique disponível.

E aqui o resultado esperado. Para testar, crie um pipeline e arraste um Assign para usar a função, ela vai estar disponível na aba Functions agrupada pelo nome dado em category do arquivo MyCustom-xquery.xml criado na sessão “2. Registro de funções”.

Custom XPath Functions JDeveloper

Você pode incluir funções personalizadas nas expressões XQuery in-line e nos recursos XQuery da mesma forma que usaria as funções fornecidas pelo Oracle Service Bus.

Também é possivel usar as funções personalizadas dentro de um recurso XSLT, segue exemplo de como usá-la em uma transformação.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:param name="arg-string"/>
  
  <xsl:template name="welcomeMessage" xmlns:ns0="xalan://br.com.parmigiani.lab.CustomXPathFunctions">
   <xsl:variable name="message" select="ns0:welcomeMessage($arg-string)" />
   <originalInput>
     <xsl:value-of select="$arg-string" />
   </originalInput>
   <result>
     <xsl:value-of select="$message" />
   </result>
 </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
        <xsl:call-template name="welcomeMessage"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Por enquanto é isso, até o próximo post

3 comentários para “Criar Funções XPath Personalizadas no OSB 12c

  1. Parabéns por mais um excelente post Ednei. O compartilhamento do seu conhecimento ajuda a toda comunidade de desenvolvedores. Continue sempre assim, um forte abraço

  2. Higor Eduardo Borges Galdino on 26 de novembro de 2018 at 8:34 said:

    Parabéns pelo conteúdo de qualidade, funções xpath personalizadas facilitam muito na hora de trabalhar com o OSB/SOA.

Deixe um comentário

Campos obrigatórios são marcados *

Post Navigation