Apache ActiveMQ

O Apache ActiveMQ Artemis é um sistema moderno de mensageria de código aberto, escrito em Java, e mantido pela Fundação de Software Apache. Atualmente encontra-se em desenvolvimento constante sendo trabalhando como o sucessor natural do tradicional Apache ActiveMQ e a próxima evolução em termos de mensageria tradicional. É comumente utilizado como uma solução de mensageria prática e de alta performance. Suportando dois mecanismos de persistência diferentes, baseados em NIO ou AIO, o Artemis consegue prover um misto de robustez, baixa latência e boa velocidade mesmo quando atuando em modo persistente.

Antes de criarmos o projeto com o Camel, precisamos criar uma instância de um broker Artemis. Esse passo pode ser realizado facilmente através de um container. O projeto Artemis fornece, junto com seu código fonte, instruções para a criação de containers. Podemos, também, utilizar containers fornecidos pela comunidade. Por exemplo:

docker run -it --rm -p 8161:8161 -p 61616:61616 -p 5672:5672 -e ARTEMIS_USERNAME=admin -e ARTEMIS_PASSWORD=admin vromero/activemq-artemis:2.15.0-alpine

Com isso temos uma instância do Artemis ouvindo nas portas 5672 (protocolo AMQP 1.0), 61616 (OpenWire, CORE, AMQP, Stomp) e 8161 (HTTP/admin). Podemos acessar a interface de administração para verificar se a instância está rodando com sucesso. Para isso basta acessar o endereço http://localhost:8161.

Uma vez que o Artemis esteja rodando com sucesso podemos seguir adiante e criar um projeto simples usando o Camel. Para isso, executamos o seguinte comando:

mvn archetype:generate -B -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=3.18.2 -DgroupId=camel-passo-a-passo -DartifactId=activemq-app-camel -Dversion=1.0.0-SNAPSHOT -Dpackage=activemq.app.camel

Assim como no caso do primeiro projeto criado anteriormente, o resultado do comando acima será um projeto básico com o Camel e alguns dos arquivos mínimos necessários para a execução. Modificaremos esse projeto para que ele envie os arquivos para filas diferentes na nossa instância do Apache Artemis.

Para a comunicação com o nosso broker Artemis, podemos utilizar o componente Simple JMS 2, também conhecido como SJMS2. Esse é um componente que implementa boas práticas do padrão Jakarta Messaging API (JMS) e fornece um mecanismo simples para troca de dados com soluções e protocolos suportados por este padrão.

O primeiro passo para modificar nosso projeto para este propósito é adicionar o componente camel-sjms2 na lista de dependências do projeto. Fazemos isso modificando o arquivo pom.xml e adicionando o seguinte na lista de dependências:

<dependency>
     <groupId>org.apache.camel</groupId>
     <artifactId>camel-sjms2</artifactId>
</dependency>

Precisamos, também, de uma provedor para os “Connection Factories”. Uma implementação concreta que provê o código necessário para a comunicação com o broker JMS. Para tal, podemos usar diversos projetos como QPid JMS, Artemis JMS e outros. Neste exemplo, usamos o QPid JMS. Desta forma, precisamos adicionar a seguinte dependência:

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-jms-client</artifactId>
    <version>0.54.0</version>
</dependency>

Dica: ao implementar uma solução profissional, é bastante provável, também, que será necessário utilizar um pool de conexões. Como por exemplo, o projeto PooledJMS.

A partir de então, pode-se criar uma instância do objeto de configuração da connection factory, configura-la com os parâmetros de conexão adiciona-lo ao contexto do Camel. Podemos adicionar os códigos a seguir no método configure da classe MyRouteBuilder.

O exemplo abaixo mostra uma configuração simples de acesso a um broker Active MQ configurado com autenticação por usuário e senha (admin/admin, os mesmos utilizados para rodar a instância do Artemis):

JmsConnectionFactory connFactory = new JmsConnectionFactory("amqp://localhost:5672");

// Usuário e senha da instância do broker Artemis
connFactory.setUsername("admin");
connFactory.setPassword("admin");

Uma vez que o objeto de configuração foi instanciado, é possível utiliza-lo para instanciar um novo componente Simple JMS 2:

Sjms2Component component = new Sjms2Component();

component.setConnectionFactory(connFactory);

Então adicionamos o componente no contexto do Camel, para que ele mapeie os endpoints sjms2 para esse componente configurado previamente:

// Mapeamos endpoint sjms2 para o componente previamente configurado
getContext().addComponent("sjms2", component);

Por fim, podemos modificar a rota para que redirecione os arquivos XML para as filas uk ou others, baseado no conteúdo dos arquivos:

from("file:src/data?noop=true")
    .choice()
        .when(xpath("/person/city = 'London'"))
            .log("UK message")
            .to("sjms2://queue/uk")
        .otherwise()
            .log("Other message")
            .to("sjms2://queue/others");

Para executar o projeto, enviando as mensagens para o Artemis, podemos rodar o seguinte comando:

mvn clean package && mvn exec:java -Dexec.mainClass="activemq.app.camel.MainApp"

Podemos checar se as mensagens foram enviadas com sucesso para o Artemis, acessando a interface de administração e verificando a existência de, pelo menos, 1 mensagem em cada um das filas “uk" e “others”.

Dica: Alguns dos connection factories comumente utilizados com o SJMS2 são: org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory org.apache.activemq.ActiveMQConnectionFactory

Dica: Fique atento para importar corretamente as classes utilizadas neste exemplo: import org.apache.camel.component.sjms2.Sjms2Component; import org.apache.qpid.jms.JmsConnectionFactory;