Spring Boot e ActiveMQ

Apache ActiveMQ é um servidor de mensageria de código aberto utilizado por grandes players do mercado que utilizam arquiteturas open-source. Mas qual é a proposta do ActiveMQ? Antes de entender o que é o ActiveMQ, temos que pensar em problemas comuns em aplicações que precisam escalar e integrar melhor seus serviços. Hoje o fluxo de informações trafegadas é infinitamente maior que 10 anos atrás e é quase impossível mensurar capacidade em termos de escalabilidade que uma aplicação pode suportar. Para entendermos melhor, vamos imaginar que você foi contratado para projetar uma arquitetura de um e-commerce que fará vendas de ingressos dos jogos da campeonato brasileiro. Como sempre você tem pouco tempo para pensar uma arquitetura. A primeira ideia é simples e rápida, o resultado é este desenho. Levando em conta a quantidade de acessos e requisições por segundo, você acha uma arquitetura resiliente? Será que o banco de dados escala? Será que o banco suporta multi-acessos? E se o banco por algum motivo cair, a compra será perdida? Podemos melhorar um pouco mais essa arquitetura deixando ela um pouco mais profissional e resiliente. Vamos lá. Vamos entender este último desenho. Agora, ao efetuar um pedido de compra os pedidos são enviados para um servidor de mensagens (Fila). A ideia da Fila é basicamente um serviço capaz de alocar mensagens. Normalmente são textos ou texto em formato Json. Neste desenho podemos dizer que a Fila aloca dados do cliente, quantidade de ingressos, valores e etc. E por fim, existe uma aplicação que faz todo o gerenciamento dos pedidos/compras. Esta aplicação lê/remove as mensagens da Fila podendo fazer validações antes de gravar no banco de dados. Agora, vamos supor que um dos requisitos é para cada venda, o cliente deve receber uma nota fiscal do ingresso. Como a nova arquitetura está bem desacoplada, ficou mais fácil "plugar" uma nova aplicação para fazer este trabalho. Daí você pensou em um novo desenho, segue: Agora a aplicação que gerencia as compras, além de gravar a venda após recuperar as mensagens na fila 1, ela envia uma mensagem também para a fila 2, onde alocará as notas fiscais dos clientes. E uma nova aplicação que gerencia as notas fiscais recupera estas mensagens e grava em uma base especifica para o setor financeiro. Mas quais os benefícios dessa nova arquitetura? A arquitetura está mais resiliente, assíncrona e tolerável a falhas, pois caso umas das aplicações por algum motivo falhe, a mensagem retorna para a fila até o reestabelecimento das aplicações. E por fim, facilita a integração de novas aplicações. E o ActiveMQ? O que ele tem haver com isso? O ActiveMQ é o serviço que provê o servidor de mensagens. No desenho, ele seria os servidores de mensagens (Filas). Lembrando que os desenhos foram uma forma de abrir a cabeça quanto a utilidade de Filas. Para entender melhor ainda, vamos apresentar um exemplo na prática de como configurar e utilizar o ActiveMQ com Spring Boot e JMS. Criando o projeto Acesse o https://start.spring.io para criar o projeto e escolher as dependências. Preencha os campos e selecione as 2 dependências (ActiveMQ 5 e Spring Web) conforme a imagem. Gere o arquivo e importe para o seu projeto. pom.xml Completo <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spring.active.mq</groupId>
<artifactId>spring-boot-active-mq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-active-mq</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> Instalando o ActiveMQ Vamos fazer o download do ActiveMQ para que o processo fique mais transparente. Mas também existe a possibilidade em utilizar a versão embutida do Spring Boot, mas dessa vez vamos apresentar da forma mais tradicional. Para este exemplo, vamos utilizar a versão clássica do ActiveMQ. Download: https://activemq.apache.org/components/classic/download/ Faça a instalação conforme seu sistema operacional: https://activemq.apache.org/getting-started Após a instalação, inicie o servidor conforme a documentação. Preenchendo o arquivo application.properties Na aplicação Spring-Boot criada, preencha o arquivo application.properties spring.activemq.broker-url=tcp://127.0.0.1:61616
spring.activemq.user=admin
spring.activemq.password=admin A primeira linha configura a URL do servidor de mensagens A segunda linha e a subsequente são os dados de autenticação Classe Ticket public class Ticket {

private String name;
private Double price;
private int quantity;

public Ticket(){}

public Ticket(String name, Double price, int quantity){
this.name = name;
this.price = price;
this.quantity = quantity;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public int getQuantity() {
return quantity;
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}

@Override
public String toString() {
return String.format("Compra de ingresso -> " +
"Name=%s, Price=%s, Quantity=%s}",
getName(), getPrice(), getQuantity());
}
} Na classe SpringBootActiveMqApplication já criada anteriormente pelo gerador, faça a seguinte alteração. @SpringBootApplication
@EnableJms
public class SpringBootActiveMqApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootActiveMqApplication.class, args);
}

@Bean
public JmsListenerContainerFactory<?> defaultFactory(
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {

DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}

@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter =
new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
} A anotação @EnableJms é o mecanismo responsável por ativar o JMS. O método defaultFactory configura e registra a factory para conectar as filas utilizando JMS. E por fim, o método jacksonJmsMessageConverter faz as conversões das mensagens trafegadas de JSON para o tipo que será passado no JmsTemplate que veremos em breve. Todos estes métodos utilizam a anotação @Bean. Métodos anotados com @Bean são gerenciados pelo contêiner do Spring. Classe TicketController package com.spring.active.mq.springbootactivemq.Controller;

import com.spring.active.mq.springbootactivemq.pojo.Ticket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TicketController {

@Autowired
private JmsTemplate jmsTemplate;

@PostMapping(value = "/buy",
consumes = MediaType.APPLICATION_JSON_VALUE)
public void buyTicket(@RequestBody Ticket ticket){
jmsTemplate.convertAndSend("compra_queue",
new Ticket(ticket.getName(),
ticket.getPrice(),
ticket.getQuantity()));
}
} Na classe TicketController, criamos o método chamado buyTicket que será responsável por enviar as mensagens para a fila chamada compra_queue através de uma requisição POST. Neste método utilizamos um objeto do tipo JmsTemplate que possibilita a conversão do objeto e o envio para a fila utilizando JMS. Classe EventListener package com.spring.active.mq.springbootactivemq.listener;
import com.spring.active.mq.springbootactivemq.pojo.Ticket;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;


@Component
public class EventListener {
@JmsListener(destination = "compra_queue",
containerFactory = "defaultFactory")
public void receiveMessage(Ticket ticket) {
System.out.println("Mensagem da fila:" + ticket);
}
} A classe EventListener é uma espécie de "ouvinte". A anotação @JmsListener define esta característica de ouvinte. Nesta mesma anotação é possível configurar o nome da fila que será "ouvida" pelo método. Resumindo, todas a mensagens enviadas para a fila compra_queue serão recebidas por este método. Acessando o serviço de Fila - ActiveMQ Após a inicialização do serviço conforme a documentação, acesse o console do serviço através de um browser http://127.0.0.1:8161/ Criando a fila Para criar a fila, clique na opção Queues na barra superior vermelha, conforme a imagem acima. No campo Queue Name digite nome da fila compra_queue conforme imagem acima e clique no botão Create. Pronto, fila criada! Iniciando a aplicação Via terminal, acesse o diretório do seu projeto e execute o comando Maven abaixo ou inicie via IDE mvn spring-boot:run Enviando mensagens Vamos usar o Postman para o envio das mensagens, caso não tenha o Postman instalado, faça o download acessando este link https://www.postman.com/downloads/ Após a instalação, acesse o Postman e preencha os campos conforme a imagem Conteúdo do Json {"name":"Joao","price":2.0,"quantity":4} Ao clicar no botão Send, acesse o console da aplicação e será possível visualizar a mensagem enviada e trafegada na fila. Acesse novamente o console do ActiveMQ e será possível ver o registro da mensagem que foi enviada para a fila. A coluna Number of Consumers é a quantidade de consumidores da fila, que no caso é realmente 1. A coluna Messages Enqueued mostra a quantidade de mensagens que foram enviadas e por fim, a coluna Messages Dequeued é o número de mensagens que foram removidas da fila. Então é isso, espero que tenha te ajudado. Até mais!

Spring Boot e ActiveMQ