Fault Policy no MDS com Java Action – Parte 2

Na primeira parte, preparamos os arquivos de fault policy e a classe Java que irá receber as informações de falha para tratativa. Agora queremos adicionar os XMLs de fault ao MDS do SOA para facilitar a localização e manutenção destes arquivos, que poderão ser utilizados por todos os projetos SOA que forem tratar exceções.

Bem, uma vez que os arquivos de Fault Policy estejam concluídos (fault-policies.xml e fault-bindings.xml) você deverá empacotá-los em um arquivo Jar.

Crie um diretório qualquer chamado Fault_Policy_Arquivos, neste diretório iremos montar a estrutura que irá ser armazenada no MDS Database, então crie os sub-diretórios na estrutura abaixo:



No prompt de comando/terminal, vá até o diretório raiz e execute o comando para criação do arquivo Jar.

jar -cf blog-faultpolicy-MDS.jar ./apps/blog/fault/*.xml

Pronto, agora vamos fazer o deploy do arquivo blog-faultpolicy-MDS.jar com as estrutura do Fault Policy no MDS.
Acesse o Enterprise Manager do servidor, clique com o botão direito em soa-infra e depois vá para Administração e por fim clique em Configuração de MDS.


Na tela de Configuração de MDS, em Importar documentos de metadados de um arquivo, selecione o blog-faultpolicy-MDS.jar que acabamos de criar e clique no botão Importar. That’s all! Não é necessário reiniciar o Weblogic!

Para utilizar o fault policy no seu projeto SOA, edite o arquivo composite.xml e adicione os comandos baixo antes da tab component.

  <property name="oracle.composite.faultPolicyFile">oramds:/apps/blog/fault/fault-policies.xml</property>
  <property name="oracle.composite.faultBindingFile">oramds:/apps/blog/fault/fault-bindings.xml</property>

Isto é o suficiente para que seu projeto utilize o fault policy com Java Class Action, configurada no MDS.

Arquivos para Download:
Projeto Jdev (Exemplo de BPEL)
Estrutura de Diretórios para o MDS
Arquivo JAR para o MDS

Fault Policy no MDS com Java Action – Parte 1

Este exemplo esta dividido em duas partes, nessa primeira parte vou demonstrar como configurar os arquivos de Fault Policy chamando uma Java Class Custom como Action para o fault. Já na segunda parte vamos ver como adicionar a configuração ao MDS do SOA, facilitando o acesso e manutenção ao fault policy.

1. Definindo o Fault Policy


Vamos começar com o exemplo de configuração dos arquivos para o Fault Policy, veja a construção dos arquivos fault-policies.xml e fault-bindings.xml

Exemplo para o arquivo fault-policies.xml.

...
<Conditions>
      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
                 name="bpelx:remoteFault">
        <condition>
          <action ref="ora-custom-retry"/>
        </condition>
      </faultName>
      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
                 name="bpelx:bindingFault">
        <condition>
          <action ref="ora-custom-retry"/>
        </condition>
      </faultName>
    </Conditions>
    <Actions>
      <Action id="ora-custom-retry">
        <javaAction className="com.lucianosilva.lab.soa.CompositeFaultHandler"
                    defaultAction="ora-human-intervention">
            <returnValue value="ERROR" ref="ora-terminate"/>
            <returnValue value="ABORT" ref="ora-terminate"/>
            <returnValue value="RETRY" ref="ora-retry"/>
            <returnValue value="MANUAL" ref="ora-human-intervention"/>
        </javaAction>
      </Action>
            <Action id="ora-retry">
          <retry>
              <retryCount>2</retryCount>
              <retryInterval>3</retryInterval>
              <exponentialBackoff/>
          </retry>
      </Action>
      <Action id="ora-replay-scope">
          <replayScope/>
      </Action>
      <Action id="ora-rethrow-fault">
          <rethrowFault/>
      </Action>
      <Action id="ora-human-intervention">
          <humanIntervention/>
      </Action>
      <Action id="ora-terminate">
          <abort/>
      </Action>
    </Actions>
...

Definição do arquivo fault-bindings.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<faultPolicyBindings version="2.0.1" xmlns="http://schemas.oracle.com/bpel/faultpolicy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <composite faultPolicy="fault-policies"/>
</faultPolicyBindings>

2. Java Action Class

Agora, com os arquivos de policy definidos, vamos construir a classe que irá receber a exception ocorrida no BPEL. No seu projeto adicione as duas classes orabpel.jar e fabric-runtime.jar, se você utiliza o JDeveloper configure-o como a imagem abaixo.

package com.lucianosilva.lab.soa;

import java.util.Collection;
import java.util.Map;

import oracle.integration.platform.faultpolicy.IFaultRecoveryContext;
import oracle.integration.platform.faultpolicy.IFaultRecoveryJavaClass;
import com.collaxa.cube.engine.fp.BPELFaultRecoveryContext;

/**
 * @author luciano silva
 *
 */
public class CompositeFaultHandler implements IFaultRecoveryJavaClass {

    private static final String RETURN_ERROR  = "ERROR";
    private static final String RETURN_MANUAL = "MANUAL";
    private static final String RETURN_RETRY  = "RETRY";

    /**
     *
     */
    public CompositeFaultHandler() {
        super();
    }

    /**
     *
     * @param iFaultRecoveryContext
     * @return
     */
    public String handleFault( IFaultRecoveryContext iFaultRecoveryContext ) {

        // print all fault details
        System.out.println("==========");
        System.out.println("Fault Policy Id : " + iFaultRecoveryContext.getPolicyId());
        System.out.println("Fault Type      : " + iFaultRecoveryContext.getType());
        System.out.println("Partnerlink     : " + iFaultRecoveryContext.getReferenceName());
        System.out.println("Port Type       : " + iFaultRecoveryContext.getPortType());

        if( iFaultRecoveryContext instanceof BPELFaultRecoveryContext ){
            //
            BPELFaultRecoveryContext bctx = (BPELFaultRecoveryContext) iFaultRecoveryContext;

            System.out.println("BPEL ActionId       : " + bctx.getActionId() );
            System.out.println("BPEL ActivityId     : " + bctx.getActivityId() );
            System.out.println("BPEL ActivityName   : " + bctx.getActivityName() );
            System.out.println("BPEL ActivityType   : " + bctx.getActivityType() );
            System.out.println("BPEL CorrelationId  : " + bctx.getCorrelationId() );
            System.out.println("BPEL PartnerLinkName: " + bctx.getPartnerLinkName() );
            System.out.println("BPEL Fault  : " + bctx.getFault().getFaultName() );
            System.out.println( bctx.getFault().getMessage() );
        }

        if( iFaultRecoveryContext.getProperties() != null ){

          System.out.println("Properties found in propertySet:");
          // print all properties defined in the fault-policy file
          Map props = iFaultRecoveryContext.getProperties();
          Collection list = props.values();
          for (String value : list) {
              System.out.println( value );
          }//

        }

        System.out.println("==========");

        return RETURN_MANUAL;
    }

    /**
     *
     * @param iFaultRecoveryContext
     */
    public void handleRetrySuccess( IFaultRecoveryContext iFaultRecoveryContext ) {
        System.out.println("SUCCESS.");
    }
}

Após compilar a classe acima, vamos empacotar em um arquivo .jar, faça isso:

 jar -cf fault-policy-javaaction.jar ./com/lucianosilva/lab/soa/*.class

Lembre-se, de usar \ se estiver no windows.

3. Adicionando Java Class (Jar) ao classpath do Weblogic

Você precisará que seu Jar seja adicionado ao classpath do Weblogic, para que em runtime a classe seja reconhecida pelo contexto e o Faut Policy funcione. O Apache Ant deve estar obrigatóriamente configurado no servidor.

O processo é muito simples, faça shutdown do servidor Weblogic, depois copie o arquivo .Jar para o diretório do servidor Weblogic $ORACLE_MIDDLEWARE_HOME/soa/modules/oracle.soa.ext_11.1.1/classes. Vá para no diretório oracle.soa.ext_11.1.1, aqui temos o build.xml, por fim, execute o Ant.

Pronto, está concluída a configuração de um exemplo para Fault Policy.
Para que as falhas do seu BPEL seja manipulada pela classe Java, as policies devem ser adicionadas ao arquivo composite.xml.

Veja na próxima parte deste post, como adicionar os XMLs de configuração do Fault Policy ao MDS e um BPEL utilizando esta configuração.

Download
Arquivos XML do Fault Policy
Projeto Java

Referências
http://docs.oracle.com/cd/E12839_01/integration.1111/e10224/bp_faults.htm
http://ant.apache.org/

Maven, Hibernate, Spring, CXF e MySql rodando no Jboss 7

Este post demonstra como usar de maneira prática o Hibernate com Spring publicando um Web Services utilizando com o Apache CXF, no Jboss 7 AS.

O primeiro passo é configurar o Maven, que irá auxiliar na automação do projeto. Acredito que é a parte mais complicada deste tutorial, já que encontrar todas as bibliotecas e dependências necessárias não é uma tarefa fácil. O pom.xml (arquivo de configuração do Maven) abaixo funciona perfeitamente para a configuração feita no nosso application-context.xml que você irá ver a seguir, você poderá fazer download da versão completa deste projeto no fim deste post.

...

	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate</artifactId>
			<version>3.2.1.ga</version>
			<exclusions>
				<exclusion>
					<groupId>asm</groupId>
					<artifactId>asm</artifactId>
				</exclusion>
				<exclusion>
					<groupId>asm</groupId>
					<artifactId>asm-attrs</artifactId>
				</exclusion>
				<exclusion>
					<groupId>cglib</groupId>
					<artifactId>cglib</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.8</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib-nodep</artifactId>
			<version>2.1_3</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-annotations</artifactId>
			<version>3.2.0.ga</version>
		</dependency>
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.unitils</groupId>
			<artifactId>unitils</artifactId>
			<version>1.0</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>
	</dependencies>
...

Vamos começar a fazer nosso serviço que irá retornar informações sobre Clubes de Futebol. Vamos mapear o Bean referente a tabela TB_CLUBES.

package com.lucianosilva.lab.entity;

@Entity
@Table(name = "TB_CLUBES")
public class Clube implements BaseEntity<Long> {
	private static final long serialVersionUID = 5541457395540986982L;

	@Id
	@Column(name = "ID_CLUBE", nullable = false)
	private Long idClube;

	@Column(name = "NOME", nullable = true)
	private String nome;

	@Column(name = "NOME_POP", nullable = true)
	private String nomePopular;

	@Column(name = "FUNDACAO", nullable = true)
	private Date dataFundacao;

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.core.BaseEntity#getId()
	 */
	@Override
	public Long getId() {
		//
		return this.idClube;
	}

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.core.BaseEntity#setId(java.lang.Object)
	 */
	@Override
	public void setId(Long id) {
		//
		this.idClube = id;
	}

//... getters and setters
}

Agora podemos construir o acesso aos dados, que faz uso de Generic DAO ocultado neste post, não se preocupe é uma prática comum, no fim do post estão os arquivos para download.

Essa classe básicamente define o que vamos ter no serviço, duas operações de retorno filtrando pelo ID e Nome.

package com.lucianosilva.lab.dao;

public class ClubesDao extends HibernateGenericRepository<Clube, Long> {

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.repository.HibernateGenericRepository#findById(java.io.Serializable)
	 */
	@Override
	public Clube findById(Long id) {
		return super.findById(id);
	}

	public ClubesDao(){
		super(Clube.class);
	}

	/**
	 *
	 * @param name
	 * @return
	 */
	public List<Clube> findByName( String name ){
		return super.findByCriteria(Expression.like("nome", name, MatchMode.ANYWHERE));
	}
}

A definição deste serviço é tão simples quanto a construção do DAO acima, não foi feito o tratamento customizado das exceções já que o objetivo não é esse e, sim demonstrar a integração dos frameworks e como devem ser configurados, nada impede de você mesmo evoluir este código.

package com.lucianosilva.lab.webservices;

@WebService
public interface ClubeService {

	@WebMethod(operationName="ListAllClubes")
	@WebResult(name = "Clube")
	public List<Clube> listAll();

	@WebMethod(operationName="FindByClubeName")
	@WebResult(name = "Clube")
	public List<Clube> findByName(@WebParam(name = "clubeName") String name);

}

Implementação do serviço.

package com.lucianosilva.lab.webservices.impl;

import java.util.List;

import javax.jws.WebService;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.lucianosilva.lab.dao.ClubesDao;
import com.lucianosilva.lab.entity.Clube;
import com.lucianosilva.lab.webservices.ClubeService;

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@WebService(endpointInterface="com.lucianosilva.lab.webservices.ClubeService")
public class ClubeServiceImpl implements ClubeService {

	private ClubesDao clubesDao; // configuracao no application-context

	public List<Clube> findByName(String name) {
		return clubesDao.findByName(name);
	}

	public List<Clube> listAll() {
		//
		return clubesDao.listAll();
	}

	/**
	 * @return the clubesDao
	 */
	public ClubesDao getClubesDao() {
		return clubesDao;
	}

	/**
	 * @param clubesDao the clubesDao to set
	 */
	public void setClubesDao(ClubesDao clubesDao) {
		this.clubesDao = clubesDao;
	}

}

Bem, até aqui nada de novo, pelo contrário tudo muito trivial. A configuração desta aplicação (application-context.xml) é o “pulo-do-gato”.

Adicionei comentários no bloco abaixo, para explicar cada parte da configuração.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xsi:schemaLocation="  

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://cxf.apache.org/core

http://cxf.apache.org/schemas/core.xsd

http://cxf.apache.org/jaxws

http://cxf.apache.org/schemas/jaxws.xsd

http://cxf.apache.org/jaxrs

http://cxf.apache.org/schemas/jaxrs.xsd"

	default-dependency-check="none" default-lazy-init="false">

	<!-- arquivo separado para a configuração dos EndPoints (WebServices) CXF veja mais abaixo -->
	<import resource="cxf-beans.xml" />

	<!-- Bean abstrato para evitar repetição de código -->
	<bean id="baseSessionFactory" abstract="true">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!-- IoC - Implementação da interface ClubesDAO -->
	<bean id="clubesDao" class="com.lucianosilva.lab.dao.ClubesDao"
		parent="baseSessionFactory" />

        <!-- Configuração do DataSource para o Connection Pool - Este JNDI name está seguindo o padrão do JBoss -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName">
			<value>java:/Laboratorio</value>
		</property>
	</bean>

	<!-- Configurações de uma Session Factories -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref local="dataSource" />
		</property>
		<property name="annotatedClasses">
			<list>
				<value>com.lucianosilva.lab.entity.Clube</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLInnoDBDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">false</prop>
			</props>
		</property>
	</bean>
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

Bem, lá no começo do application-context.xml fizemos o import da configuração do CXF, segue a descrição do arquivo cxf-beans.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<!-- Configurações do Apache CXF -->
	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

	<!-- Configurações do endpoint WSDL -->
	<jaxws:endpoint id="clubeService" depends-on="clubeServiceImpl"
		implementor="#clubeServiceImpl" address="/ClubeService">
	</jaxws:endpoint>

	<!-- Bean que implementa o endpoint do nosso webservice -->
	<bean id="clubeServiceImpl" class="com.lucianosilva.lab.webservices.impl.ClubeServiceImpl">
		<property name="clubesDao" ref="clubesDao" />
	</bean>
</beans>

Compile, empacote e faça deploy no Jboss, agora vamos ver o serviço rodando no soapUI.

 

Por fim, você viu a configuração de um serviço simples, com acesso ao banco de dados utilizando DataSource, a qual considero importantíssimo como exemplo, já que NÍNGUEM utiliza a configuração do application-context informando os parâmetros do banco de dados (exceto para o uso do JUnit).

Você pode evoluir este código implementando o controle de erros com WebFault e também utilizando o Autowired no Spring, aumentando o controle da sua aplicação e diminuindo a configuração manual.

Download

 

Criando, Populando e Consumindo Advanced Queue com BPEL – Parte 3/3

E por fim, vamos fazer uso da AQ que foi criada e populada com dados fixos, veja Parte 1 e Parte 2.
O processo de consumo de uma fila chamado de Dequeue, quando executado remove o registro da tabela controladora (Queue Table).

Na camada Oracle Middleware o consumo desta AQ pode ser feito utilizando o Oracle JCA Adapter for Advanced Queue (AQ Adapter) do BPEL.

Nota: Não serão detalhados os procedimentos para a configuração do AQ Adapter no Weblogic, e também a construção básica de um Composite e BPEL, veja as referências deste post.

Consumindo Advanced Queue com BPEL

Crie um novo projeto SOA, e adicione um processo BPEL assíncrono, dê o nome de BPELProcessQueue.

Criando o BPEL Assincrono

Criando o BPEL Assíncrono

Configure o banco de dados em que foi criada a fila, utilizando o usuário proprietário da AQ.
Arreste o componente AQ Adapter para o processo BPEL, e faça a configuração informando o nome, nome da fila e tipo de uso (enqueue / dequeue) neste caso iremos fazer o Dequeue.

Alguns passos básicos foram ocultados, preencha apenas as configurações a seguir e utilize o next-next-finish.

AQ Adapter

Selecione a configuração Dequeue.

AQ Adapter - Dequeue

Selecione o nome da fila que estamos utilizando como exemplo – “XXAR_INVOICE_QTAB”.

AQ Adapter - Selecionando Queue

Pronto. A fila está preparada para fazer parte do fluxo BPEL, adicione um Receive e associe ao Adaptador, crie uma variável de output que irá conter o tipo de dados da fila.

Fluxo BPEL

Bem, com isso feito você já tem o controle total da fila e poderá fazer uso dos dados como quiser, veja abaixo um Assign simples, apenas demonstrando o resultado do nosso receive.

BPEL Assign

Conclusão
O uso do Oracle AQ pode ser aplicado a diversas situações, uma delas quando está trabalhando com sistemas limitados a tecnologia de Web Services, este recurso é muito útil também em casos que toda a programação está centralizada no banco de dados. Tendo em vista que a implementação e desenvolvimento são razoávelmente rápidos, utilizar a Oracle AQ fornece um ganho enorme para a plataforma de integração.

A seguir você poderá fazer download do projeto utilizado como exemplo e também os scripts para construção da fila.

Downloads

Referência

\o/

Criando, Populando e Consumindo Advanced Queue com BPEL – Parte 2/3

Com a estrutura da AQ criada, o próximo passo ainda utilizando o PLSQL é o envio das informações para a fila. O enqueue deve ser feito utilizado a API Core DBMS_AQ.

Populando (Enqueue)

O enfileiramento é um processo simples, uma vez que as variáveis foram declaradas, basta popular o type da mensagem que será enviada a fila, e fazer uso do dbms_aq.enqueue.

Este exemplo demonstra o enfileiramento de um único registro na fila, mas você pode evoluir o código fazendo o preenchimento com multiplos registros.

Veja como popular o objeto correspondente a mensagem com dados fixos.


    --
    -- Formatacao da Mensagem para o Enqueue com dados fake
    --
    MESSAGE := XXAR_KEY_INVOICE( INVOICE_NUM => 10001,
                                 SOURCE_NAME => 'core system',
                                 TOTAL_AMOUNT => 139.99,
                                 DESCRIPTION => 'White T-Short'
                               );
--

Uma vez que a mensagem foi preenchida, a próximo ação é o enfileiramento da mensagem, um procedimento tão simples quanto o anterior. O commit da transação é obrigatório.

    --
    -- Enqueue (enfileiramento)
    dbms_aq.enqueue(queue_name           => p_queue, -- nome da fila
                    payload              => MESSAGE, -- mensagem
                    enqueue_options      => enqueue_options,
                    message_properties   => message_properties,
                    msgid                => message_handle);

    commit; --
--

Pronto, feito isto já é possível consultar a Queue Table e verificar o novo registro que acabou de ser inserido.

SELECT * FROM XXAR_INVOICE WHERE 1 = 1 ORDER BY enq_time DESC;

A coluna State da Queue Table corresponde ao status do registro.

dbmsaq.READY     = 0
dbmsaq.WAITING   = 1
dbmsaq.PROCESSED = 2
dbmsaq.EXPIRED   = 3

O registro na fila está pronto para ser consumido, e vou demonstrar isto na próxima parte utilizando o BPEL.

Download