12
Mar

Publicação na OTN: Oracle CEP e Posicionamento

Dia 10 meu novo artigo sobre Oracle CEP foi publicado na OTN.

O artigo aborda casos de uso interessantes sobre Oracle CEP envolvendo localização e posicionamento e mostra como podemos enviar os dados de posicionamento a partir da JSR-179.

Acesse já o artigo em: http://www.oracle.com/technology/pub/articles/amadei-cep.html

Este blog não expressa direta ou indiretamente quaisquer opinião da Oracle.


free b2evolution skin
23
Feb

Classes Java que você só ouviu falar - javax.servlet.http.HttpSessionBindingListener

Nesse post continuo a abordar algumas classes Java que dificilmente você já utilizou. Nesse caso veremos a interface javax.servlet.http.HttpSessionBindingListener.

Essa interface quando implementada por uma classe e uma instância dessa classe é colocada na sessão, o método valueBound é invocado, notificando que o objeto foi adicionado à sessão. Quando o objeto é retirado da sessão (ou substituído) o método valueUnbound é invocado.

A grande diferença entre essa interface e os outros listeners, é que ela é implementada no próprio objeto, enquanto que os outros listeners são objetos externos notificados de eventos.

A seguir vemos um objeto que implementa o listener:

package br.com.amadei.blog.listener;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class Person implements HttpSessionBindingListener {

	@Override
	public void valueBound(HttpSessionBindingEvent event) {
		System.out.println("Value bound: " + event);
	}

	@Override
	public void valueUnbound(HttpSessionBindingEvent event) {
		System.out.println("Value unbound: " + event);
	}

}


Uma vez que esse objeto é colocado na sessão conforme código a seguir:

	Person person = new Person();
	session.setAttribute("person", person);


O seguinte é impresso no console, mostrando que nosso listener foi notificado:


Value bound: javax.servlet.http.HttpSessionBindingEvent[source=org.apache.catalina.session.StandardSessionFacade@1d38b87]

 

Quando o objeto é removido, temos o seguinte impresso:


Value unbound: javax.servlet.http.HttpSessionBindingEvent[source=org.apache.catalina.session.StandardSessionFacade@1d38b87]

Você deve ter reparado que não houve alteração no web.xml para registro do listener. Realmente, não é necessário nada além da implementação da interface para que o objeto seja notificado que ELE foi associado à sessão.

É isso. Agora cabe a você encontrar um caso de uso para aplicar essa funcionalidade.


free b2evolution skin
16
Dec

Classes Java que você só ouviu falar - parte 1 - java.util.Scanner

A classe java.util.Scanner passou a fazer parte da gama de classes que acompanham uma instalação do Java a partir da versão 5.

Seu grande propósito é escanear texto e efetuar o parse em primitivos e strings baseando-se em expressões regulares para tal.

A seguir vemos um exemplo muito simples onde você pode observar a classe em funcionamento:


    Scanner sc = new Scanner(System.in);
    while(sc.hasNextInt()) {
      int i = sc.nextInt();
      System.out.println(i);  
    }


No exemplo apresentado, o loop continua executando até que você deixe de digitar números e digite algum outro tipo de caractere

Um outro exemplo muito interessante é o seguinte:


  public static void main(String[] args) throws Exception {

    Scanner sc = null;

    try {
      sc = new Scanner(new FileReader("Arquivo.txt")).useDelimiter(",");
      while (sc.hasNextInt()) {
        System.out.println("Int encontrado: " + sc.nextInt());
      }
    } finally {
      sc.close();
    }
  }


Nesse exemplo, o arquivo denominado Arquivo.txt deve conter o seguinte:


1,2,3,4,5,6,7,8

Caso o arquivo contenha a separação por vírgula com espaços, o exemplo já não funcionará.
É aí que a classe java.util.Scanner mostra seu poder. Se você especificar uma expressão regular corretamente, veremos que é possível se adequar a esse tipo de cenário e especificar algo como 1, 2,3,     4,5,6,7,8 no arquivo, ainda obtendo o comportamento esperado.

O exemplo a seguir mostra o código com a expressão regular que atende ao cenário apresentado:


  public static void main(String[] args) throws Exception {

    Scanner sc = null;

    try {
      sc = new Scanner(new FileReader("Arquivo.txt"))
        .useDelimiter("(\\s)*,(\\s)*");
      while (sc.hasNextInt()) {
        System.out.println("Int encontrado: " + sc.nextInt());
      }
    } finally {
      sc.close();
    }
  }


Apresentei aqui uma classe Java que você provavelmente ainda não conhecia ou se conhecia, dificilmente já tinha usado. Espero que tenha gostado!


free b2evolution skin
25
Nov

Validação semântica de XML usando Schematron no Oracle Mediator 11g

O Oracle Mediator permite o uso da tecnologia Schematron para realizar a validação semântica de documentos XML.

Conforme consta na Wikipedia: “Em linguagens de markup, Schematron é uma linguagem de validação baseada em regras para realizar afirmações sobre a presença ou não de padrões em árvores XML”. O schematron se baseia em regras na forma de expressões ao invés de utilizar gramáticas pré-definidas para validação das árvores XML, o que permite criar regras mais flexíveis e sensíveis ao contexto do XML.

Nesse exemplo veremos como forçar que para um XML representando uma pessoa física seja informado o CPF e para um XML representando uma pessoa jurídica seja informado o CNPJ.

Esse problema poderia ser facilmente resolvido com o estabelecimento de dois tipos XSD, um para cada tipo de pessoa, mas às vezes não temos a liberdade de modificar os tipos XSD e necessitamos de uma validação que leve em consideração o contexto em que se está trabalhando no momento.

Com o uso de Schematron podemos implementar outros casos de uso interessantes, além do que veremos como exemplo nesse post. A seguir, alguns exemplos:

  1. Validações simples da existência de elementos ou atributos;
  2. Validar a obrigatoriedade da presença de elementos ou atributos em decorrência da presença e/ou valorização de outros elementos ou atributos;
  3. Validações envolvendo data e hora em relação à data e hora atual: forçar que a data e hora estejam no passado ou no futuro, garantir que a idade informada seja compatível com a data de nascimento;
  4. Conteúdos obrigatórios ou proibidos em elementos e atributos;

Para a criação do projeto, onde veremos o uso do Schematron na prática, crie uma aplicação conforme pode ser visto a seguir:



Solicite a criação do projeto do tipo SOA e nomeie-o CadastroPessoa, conforme vemos a seguir e na tela seguinte entre com “Empty Composite” e clique em Finish.




Crie um XML Schema na pasta XSD de seu projeto com o seguinte conteúdo:


<schema attributeFormDefault="unqualified" elementFormDefault="qualified"
        targetNamespace="http://xmlns.oracle.com/CadPessoa"
        xmlns:tns="http://xmlns.oracle.com/CadPessoa"
        xmlns="http://www.w3.org/2001/XMLSchema">

    <element name="Pessoa" type="tns:PessoaType"/>

    <complexType name="PessoaType">
        <sequence>
            <element name="Nome" type="string"/>
            <element name="Tipo">
                <simpleType>
                    <restriction base="string">
                        <enumeration value="PF"/>
                        <enumeration value="PJ"/>
                    </restriction>
                </simpleType>
            </element>
            <choice>
                <element name="CPF" type="string"/>
                <element name="CNPJ" type="string"/>
            </choice>
        </sequence>
    </complexType>
</schema>


Esse XSD especifica um tipo para definir uma pessoa e depois um elemento de tal tipo.

O problema: esse tipo PessoaType define um tipo genérico tanto para pessoas físicas quanto para pessoas jurídicas. O grande problema é que temos que garantir que para pessoas físicas é especificado um CPF e para pessoa jurídica um CNPJ, o que não é possível via XSD (poderíamos usar herança e especialização, porém não é o caso). Usaremos schematron para isso.

Após isso, criaremos nosso serviço no mediator, que servirá de porta de entrada. Arraste um objeto do tipo Mediator para o centro da composite. Defina seu nome como “CadastroPessoa”, o template como “One-Way Interface” e como o tipo de dados de input selecione no XSD recém-criado o elemento Pessoa. A figura a seguir ilustra a configuração do mediator:




Dê um duplo clique no mediator, abrindo a tela de edição das regras de roteamento. Como é apenas um exemplo, rotearemos para um processo BPEL que efetuará um log no console.

Arraste um componente do tipo BPEL process para a composite, nomeie-o como CadastroPessoaProcess, use One-Way como template e indique que ele também recebe um elemento Pessoa como entrada. A imagem a seguir ilustra isso:




Após isso, na tela de configuração da composite ligue o mediator ao BPEL, conforme apresentado a seguir:




Edite seu processo BPEL e arraste uma ação do tipo Java Embedded. Dentro dessa ação, efetue um logging conforme a seguir:


System.out.println("Pessoa Cadastrada!");


O que irá imprimir no console a mensagem "Pessoa Cadastrada!".

Volte à edição da composite, efetue um duplo clique no mediator e marque o checkbox “Validate Syntax (XSD)”. Crie também uma transformação para o envio do tipo pessoa para o processo BPEL. O Mediator deve ficar assim:




Efetuando o deployment de seu processo agora, você verá que ele já funciona. Experimente cadastrar uma pessoa física com um CNPJ ou uma jurídica com CPF. Isso é possível, porém é uma falha. Veremos agora como barrar isso via schematron.

Crie um novo arquivo parar armazenarmos as regras em formato schematron na pasta SOA Content do Jdeveloper denominado validaTipoPessoa.sch.

Dentro desse arquivo, entre com:


<schema xmlns="http://www.ascc.net/xml/schematron" >
     <ns uri="http://xmlns.oracle.com/CadPessoa" prefix="ns"/>
     <pattern name="Valida Documento">
          <rule context="ns:Pessoa">
                <assert test="(ns:Tipo = 'PF' and ns:CPF) or (ns:Tipo = 'PJ' and ns:CNPJ)">
                    O documento nao casa com o tipo da pessoa.
                </assert>
          </rule>
     </pattern>
</schema>


Veja que o teste realizado verifica se o tipo da pessoa casa com a presença do documento correto.

Volte à tela de edição das regras de roteamento do mediator e na seção “Validate Semantic” clique em “Select schematron validation file” na tela Validations clique em Add, mantenha request selecionado em Part e localize o arquivo validaTipoPessoa.sch. A configuração do mediator deve ficar conforme apresentado a seguir:




Efetue deploy novamente e veja que agora não é possível informar o documento que não esteja de acordo com o tipo da pessoa. Ao testar o serviço com um documento que não casa com o tipo da pessoa, a seguinte mensagem pode ser observada na console de testes:


oracle.sysman.emSDK.webservices.wsdlapi.SoapTestException: 
oracle.tip.mediator.infra.exception.MediatorException: ORAMED-01301:[Payload custom validation]Schematron validation fails with error O documento nao casa com o tipo da pessoa. Possible Fix:Fix the payload.


Fecho aqui o post sobre schematron. Se você trabalha ou se interessa por tecnologias envolvendo XML ou Web Services, fique atento a esse padrão emergente. Ele traz uma série de benefícios e funcionalidades únicas.


free b2evolution skin
9
Nov

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:

  1. Recebemos a requisição do cliente.
  2. Enviamos a consulta de crédito na forma de um arquivo
  3. Recebemos a resposta também na forma de um arquivo.
  4. 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.


free b2evolution skin

:: Next >>