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.
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.
Aqui eu tenho um repositório contendo um projeto SpringBoot com ActiveMQ: https://github.com/jpjavagit/jms-active-mq , vale a pena dar uma olhada!
Material de estudo
Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s):
Spring Microservices in Action (Versão Inglês) cobre os princípios de microserviços utilizando Spring, criação de aplicações Spring Boot utilizando Spring Cloud, resiliência, como fazer o deploy e exemplos da vida real com boas práticas de desenvolvimento.
Spring MVC Beginner's Guide: Beginner's Guide (Versão Inglês) cobre os conceitos fundamentais do Spring como a arquitetura, fluxos de requisições, Bean validation, como controlar os fluxos de exceções, utilização de REST e Ajax, Testes e muito mais. Este livro é uma excelente escolha para você que queira entender mais a fundo sobre os fundamentos do Spring. Spring é um Framework Java contendo diferentes projetos, sendo que Spring MVC é um deles. Adquirindo um bom fundamento de Spring MVC, você estará apto para atuar em desafios utilizando qualquer projeto do Framework Spring.
Learn Microservices with Spring Boot: A Practical Approach to RESTful Services using RabbitMQ, Eureka, Ribbon, Zuul and Cucumber (Versão Inglês) cobre as principais características do ecosistema Spring utilizando Spring Boot, como a criação de microserviços, arquitetura baseada em eventos, utilização de RabbitMQ como recurso de mensageria, criação de serviços RESTful e muito mais. Este livro é uma excelente escolha para você que deseja conhecer mais sobre o funcionamento e os recursos oferecidos pelo Spring Boot.
Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção!
Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta.
Comentários