Utilizando Oracle Advanced Queuing (AQ) com Spring Data Source e JDBC para Processamento Assíncrono

Introdução

O Oracle Advanced Queuing (AQ) é uma solução de enfileiramento nativa do Oracle Database, projetada para gerenciar mensagens e processos assíncronos. Quando integrado ao Spring Data Source e JDBC, o Oracle AQ se torna uma ferramenta poderosa para comunicação assíncrona em sistemas distribuídos. Este artigo detalha como configurar e utilizar o Oracle AQ com Spring Data Source e JDBC para realizar operações de enfileiramento e desenfileiramento de mensagens.

Configuração do Spring Data Source

1. Configuração via application.properties

Essa abordagem é a maneira mais simples e recomendada para configurar o DataSource quando você está usando Spring Boot. Aqui está um exemplo de configuração:

spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=seu_usuario
spring.datasource.password=sua_senha
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
2. Configuração Programática (opcional)

Se você precisar de uma configuração mais personalizada ou condicional, você pode definir um DataSourceConfig programático como uma opção secundária. Aqui está um exemplo de como fazer isso:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
        dataSource.setUsername("seu_usuario");
        dataSource.setPassword("sua_senha");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

A anotação @ConditionalOnMissingBean garante que essa configuração só será usada se não houver outro DataSource ou JdbcTemplate definido, permitindo que a configuração via application.properties seja priorizada.

Enfileiramento de Mensagens

Para enfileirar uma mensagem em uma fila do Oracle AQ, use uma chamada PL/SQL através do JdbcTemplate do Spring. O exemplo abaixo mostra como enfileirar uma mensagem:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class QueueService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void enqueueMessage(String queueName, String message) {
        String enqueueSql = "DECLARE " +
                            "  enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T; " +
                            "  message_properties DBMS_AQ.MESSAGE_PROPERTIES_T; " +
                            "  message_id RAW(16); " +
                            "  message RAW(100); " +
                            "BEGIN " +
                            "  message := UTL_RAW.CAST_TO_RAW(?); " +
                            "  DBMS_AQ.ENQUEUE( " +
                            "    queue_name => ?, " +
                            "    enqueue_options => enqueue_options, " +
                            "    message_properties => message_properties, " +
                            "    payload => message, " +
                            "    msgid => message_id " +
                            "  ); " +
                            "  COMMIT; " +
                            "END;";

        jdbcTemplate.update(enqueueSql, message, queueName);
    }
}

Desenfileiramento de Mensagens

Para desenfileirar uma mensagem de uma fila do Oracle AQ, utilize uma chamada PL/SQL através do JdbcTemplate. O exemplo a seguir mostra como desenfileirar uma mensagem:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class QueueService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public String dequeueMessage(String queueName) {
        String dequeueSql = "DECLARE " +
                            "  dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T; " +
                            "  message_properties DBMS_AQ.MESSAGE_PROPERTIES_T; " +
                            "  message_id RAW(16); " +
                            "  message RAW(100); " +
                            "BEGIN " +
                            "  DBMS_AQ.DEQUEUE( " +
                            "    queue_name => ?, " +
                            "    dequeue_options => dequeue_options, " +
                            "    message_properties => message_properties, " +
                            "    payload => message, " +
                            "    msgid => message_id " +
                            "  ); " +
                            "  DBMS_OUTPUT.PUT_LINE(UTL_RAW.CAST_TO_VARCHAR2(message)); " +
                            "  COMMIT; " +
                            "END;";

        return jdbcTemplate.queryForObject(dequeueSql, new Object[]{queueName}, String.class);
    }
}

Exemplo de Uso

A seguir, um exemplo de como utilizar o serviço QueueService para enfileirar e desenfileirar mensagens:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class QueueRunner implements CommandLineRunner {

    @Autowired
    private QueueService queueService;

    @Override
    public void run(String... args) throws Exception {
        // Enfileirar uma mensagem
        queueService.enqueueMessage("my_queue", "Minha mensagem");

        // Desenfileirar uma mensagem
        String message = queueService.dequeueMessage("my_queue");
        System.out.println("Mensagem desenfileirada: " + message);
    }
}

Conclusão

Integrar o Oracle Advanced Queuing (AQ) com Spring Data Source e JDBC é uma solução poderosa para implementar processamento assíncrono em aplicações que já utilizam o Oracle Database. Através das operações de enfileiramento e desenfileiramento descritas neste artigo, é possível aproveitar as vantagens do AQ, como durabilidade e confiabilidade das mensagens, para construir sistemas distribuídos eficientes e escaláveis. Essa abordagem garante que diferentes partes da aplicação possam se comunicar de forma assíncrona, melhorando a robustez e a capacidade de resposta do sistema como um todo.