Correlation Sets no Oracle BPEL PM
Correlacionando o processo com o conteúdo de um arquivo recebido
O Oracle BPEL PM dispõe de uma funcionalidade chamada de Correlation Sets. Essa funcionalidade permite localizar um processo em execução, aguardando o recebimento de informações, por exemplo, e continuar seu processamento. Essa localização do processo se dá através da correlação entre um valor já armazenado pelo processo e um valor recebido de uma fonte de dados externa.
Um cenário interessante para se pensar é a solicitação de um empréstimo onde no meio de sua lógica o processo necessita enviar um arquivo para uma verificação de crédito do solicitante e, após isso, receber a resposta pertencente àquela solicitação em específico, dando continuidade no processo a partir deste ponto.
Para o exemplo apresentado, dentro do JDeveloper 11g, crie uma nova aplicação conforme apresentado a seguir:

Clique em Next e entre com as informações para criação do projeto:

Clique em Next e escolha o template para a composite:

Clique em Next e crie o processo BPEL:

Neste exemplo teremos como entrada do processo um identificador da solicitação de empréstimo que será um valor único entre todas as solicitações. Esse identificador também será o dado que utilizaremos para realizar as correlações. Além disso receberemos o CPF, nome e valor solicitado para empréstimo como entrada.
Para que seja possível receber tais valores, dentro da estrutura do processo BPEL, em SOA Content > xsd, abra SolicitacaoEmprestimoProcess.xsd. O que será exibido será similar ao apresentado a seguir:
<?xml version="1.0" encoding="UTF-8"?> <schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/BlogAmadei/SolicitacaoEmprestimo/SolicitacaoEmprestimoProcess" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="process"> <complexType> <sequence> <element name="input" type="string"/> </sequence> </complexType> </element> <element name="processResponse"> <complexType> <sequence> <element name="result" type="string"/> </sequence> </complexType> </element> </schema>
Altere a estrutura do elemento process para que fique igual à apresentada:
<element name="process">
<complexType>
<sequence>
<element name="id" type="int"/>
<element name="nome" type="string"/>
<element name="cpf" type="string"/>
<element name="valor" type="double"/>
</sequence>
</complexType>
</element>
Essa estrutura representa os dados que o processo recebe como entrada a partir da solicitação de um cliente.
Enviando e recebendo informações via Arquivo
Para a manipulação, escrita e leitura de arquivos dentro de um processo BPEL utilizamos uma instância de um adaptador com esse propósito. Para adicionar o adaptador a seu processo, na janela Component Palette selecione BPEL Services, e arraste um File Adapter para a área Partner Links de seu processo BPEL. Caso seja exibida a tela de boas vindas, clique em Next. Em service name entre com EnvioArquivo. Em adapter interface, mantenha selecionado “Define from operation and schema” e clique em next. A próxima tela exibida é “Operation”. Selecione “Write File” clique em next. Será exibida uma tela similar à apresentada a seguir, preencha as informações conforme apresentado e clique em Next.

Na próxima tela, clique em “Define Schema for Native Format” pois gravaremos o arquivo no formato separado por vírgulas (CSV). Na tela de configuração do formato do arquivo, clique em Next na tela de boas vindas. Na próxima tela mantenha “Delimited” selecionado e clique em Next.
Crie um arquivo a.txt na pasta /temp/files com o conteúdo similar ao apresentado a seguir:
1,99999999999,Daniel C. Amadei,10000
Nesse arquivo temos os campos na sequência como id, cpf, nome e total requisitado. Na tela File Description utilize esse arquivo como exemplo para criação do schema. A configuração ficará similar à apresentada a seguir:

Clique em Next e Next novamente. No campo “Enter a name for element that will represent record” entre com registro. Clique em Next duas vezes e na tela exibida configure os nomes dos campos para que não fiquem como C1, C2, etc. A imagem a seguir exibe como deve ficar:

Clique Next, altere o tipo do elemento total para xsd:decimal ao invés de xsd:int editando o código-fonte! Clique em Next e Finish. Na tela de configuração do adaptador clique em Next e Finish.
Adicione um nó do tipo Invoke após o nó receiveInput, nomeie o novo nó como enviaArquivo e ligue-o à instância do adaptador. Clique no botão + para criação da variável de entrada. O resultado deve ser similar à tela apresentada a seguir:

Precisamos valorizar os dados para escrita do arquivo. Adicione um nó Transform antes do nó enviaArquivo. Nomeie-o transformEnviaArquivo. Edite o nó, selecione como entrada a variável inputVariable e como destino a variável enviaArquivo_Write_InputVariable e clique no botão + para criação do arquivo de transformação.
Realize a transformação conforme apresentada a seguir:

Até aqui temos a criação do arquivo funcionando corretamente. Precisamos receber o resultado.
Adicione mais uma instância de file adapter. Nomeie a instância como RecebimentoResultado. Selecione a operação como Read File. Na seleção para diretórios entre com /temp/files. Na tela File Filtering mantenha File Wildcards e no campo “Include Files with Name Pattern” entre com *.resp. Clique em Next, altere a frequência de polling para 10 segundos. Crie um arquivo b.txt na pasta /temp/files com o seguinte conteúdo:
1,APROVADO
E utilize esse arquivo como template para definição do schema nativo.
Para recebermos as informações lidas pelo arquivo crie um nó do tipo Receive nomeado recebeResultado após o nó enviaArquivo. Ligue-o com o adaptador RecebimentoResultado, criando uma variável para receber as informações lidas.
Crie um bloco assign após o nó recebeResultado e nomeie-o valorizaRetorno. Crie uma instrução de cópia entre os nós /ns3:registro/ns3:result e /client: processResponse/client:result. A cópia deve ser idêntica à apresentada a seguir:

Entendendo o que aconteceu até aqui:
- Recebemos a requisição do cliente.
- Enviamos a consulta de crédito na forma de um arquivo
- Recebemos a resposta também na forma de um arquivo.
- Respondemos para o cliente de forma assíncrona se o empréstimo dele foi aprovado ou não.
Porém dentro deste fluxo existe uma falha bastante grave. Como sabemos que o arquivo que estamos recebendo é referente àquele determinado processo de solicitação de empréstimo? No cenário atual simplesmente não sabemos. Com isso, precisamos de um mecanismo para correlacionar o processo que foi iniciado com o arquivo que foi recebido e é aí que os correlation sets mostram seu poder.
Usaremos um correlation set para correlacionar a propriedade ID recebida pelo processo com o ID retornado como resposta à análise de crédito, dando continuidade ao fluxo do processo.
Para estabelecer a correlação, precisamos primeiramente criar o correlation set que é uma abstração das propriedades que se deseja correlacionar e depois mapeamos propriedades reais ao correlation set. Para isso, na janela de estrutura do projeto vá até Correlation Sets > Process > Correlation Sets, clique com o botão direito e “Create Correlation Set...”. A imagem a seguir ilustra esse passo:

Ao surgir a tela para criação das propriedades, clique em Add... e crie a propriedade Id do tipo xsd:int conforme podemos ver a seguir:

Agora que criamos o correlation set, precisamos mapear as propriedades. Para isso, criamos o que é chamado de Property Alias. Na janela de estrutura, clique com o botão direito sobre Property Aliases > Create Property Alias.
Na tela de mapeamento, selecione Type Explorer > Message Types > Partner Links > solicitacaoemprestimoprocess_client > SolicitacaoEmprestimoProcess.wsdl > Message Types > SolicitacaoEmprestimoProcessRequestMessage > Part – payload. Em Query pressione ctrl+barra espaço e entre com /client: process/client:id.
Repita a operação e selecione Type Explorer > Message Types > Project WSDL Files > RecebimentoResultado.wsdl > Message Types > Read_msg > Part – body e em Query selecione /ns1:registro/ns1:id. A imagem a seguir ilustra tal cenário:

Por fim, precisamos apenas valorizar as propriedades. Dê um duplo clique em receiveInput. Acesse Correlations, local onde podemos especificar o correlation set a ser utilizado. Clique em Add e selecione o correlation set que acabamos de criar. Após isso altere a propriedade Initiate para yes para indicar que devemos inicializar o correlation set nesse passo, conforme vemos a seguir:

Repita a operação para o nó “recebeResultado”, deixando a propriedade Initiate valorizada com “no” pois já inicializamos esse correlation set.
Agora precisamos apenas testar. Acesse o Enterprise Manager através da url http://<ip>:<porta>/em onde ip e porta são do seu servidor de administração.
Teste a composite utilizando os seguintes dados:

Após isso, acessando a pasta /temp/files, temos um arquivo analise_<sequencial>.req. Abrindo o arquivo, vemos que ele foi gravado com as informações que disponibilizamos. Isso é exibido a seguir:

Crie agora um arquivo analise_3.resp na pasta /temp/files com o conteúdo 1,APROVADO.
Veja que o processo que antes estava pendente:
Agora é finalizado após a leitura do arquivo:
Repita o teste, porém no arquivo de resposta altere o ID de 1 para 2 por exemplo. Você verá que o arquivo é lido, porém seu processo fica parado pois não possui o ID correspondente.
É nesse ponto que vemos todo o poder e utilidade no uso dos correlation sets.