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. 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.