1. Introducción
Bienvenidos a un nuevo post de nuestro querido blog!. En esta ocasión veremos cómo instalar RabbitMQ en Docker y cómo escribir y leer mensajes de una cola.
Os podéis descargar el código de ejemplo de mi GitHub aquí.
Tecnologías empleadas:
- Java 8
- Gradle 3.1
- SpringBoot 1.5.2.RELEASE
- Spring 4.3.7.RELEASE
- RabbitMQ 3.6.9
- Erlang 19.3
2. Instalación de RabbitMQ en Docker
Como viene siendo costumbre en este blog utilizaremos Docker para instalar el software adicional que vamos necesitando. Si no estás muy familiarizado con esta nueva tecnología puedes ver el post en donde hablamos de qué es Docker y para qué lo utilizamos.
Especificamos en nuestro fichero docker-compose.yml que queremos arrancar un contenedor de la imagen rabbitmq donde se configure el virtualhost / para el usuario admin con la password admin.
rabbit1: image: "rabbitmq" environment: RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG" RABBITMQ_DEFAULT_USER: "admin" RABBITMQ_DEFAULT_PASS: "admin" RABBITMQ_DEFAULT_VHOST: "/" ports: - "15672:15672" - "5672:5672" volumes: - "./enabled_plugins:/etc/rabbitmq/enabled_plugins"
Además montamos en el directorio /etc/rabbitmq/
el fichero enabled_plugins donde establecemos que queremos configurar los plugins de gestión web.
Arrancamos nuestro contenedor
Vamos a la url http://localhost:15672
3. Configurando microservicio SpringBoot
Dependencia y Main
Para conectarnos a RabbitMQ es necesario añadir la dependencia org.springframework.boot:spring-boot-starter-amqp
a nuestro build.gradle
group 'org.hernandez.ramirez.jorge.pruebaconcepto' version '1.0-SNAPSHOT' buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE") } } apply plugin: 'java' apply plugin: 'idea' apply plugin: 'org.springframework.boot' sourceCompatibility = 1.8 springBoot { mainClass = "com.jorgehernandezramirez.spring.springboot.rabbitmq.Application" } repositories { mavenCentral() } dependencies { compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-amqp") }
Main que arranca Spring Boot
package com.jorgehernandezramirez.spring.springboot.rabbitmq; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public Application(){ //Para Spring } public static void main(String[] args) { new SpringApplication(Application.class).run(args); } }
Configuración
Para configurar la conexión a RabbitMQ debemos crear los siguientes beans.
@Bean public ConnectionFactory connectionFactory() throws Exception { final CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(host); connectionFactory.setPort(port); connectionFactory.setUsername(user); connectionFactory.setPassword(password); connectionFactory.setVirtualHost(virtualhost); return connectionFactory; } @Bean public RabbitTemplate rabbitTemplate() throws Exception { return new RabbitTemplate(connectionFactory()); }
Hasta ahora no hemos creado ninguna cola dentro de nuestro contenedor de RabbitMQ. Esto lo haremos desde el arranque del contexto de Spring. Crearemos
- Exchange
- Queue
- Vincularemos Exchange al Queue
Si la cola y el exchange no existen se crea. Si existe no se hace nada.
@Bean public Queue queue() { return new Queue(QUEUE_NAME); } @Bean public TopicExchange exchange() { return new TopicExchange(EXCHANGE_NAME); } @Bean public Binding binding(Queue queue, TopicExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY); }
Mostramos todo en el fichero RabbitConfiguration.
package com.jorgehernandezramirez.spring.springboot.rabbitmq.config; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitConfiguration { public static final String QUEUE_NAME = "test-queue"; private static final String EXCHANGE_NAME = "test-queue-exchange"; @Value("${rabbitmq.host}") private String host; @Value("${rabbitmq.port}") private Integer port; @Value("${rabbitmq.user}") private String user; @Value("${rabbitmq.password}") private String password; @Value("${rabbitmq.virtualhost}") private String virtualhost; @Bean public ConnectionFactory connectionFactory() throws Exception { final CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(host); connectionFactory.setPort(port); connectionFactory.setUsername(user); connectionFactory.setPassword(password); connectionFactory.setVirtualHost(virtualhost); return connectionFactory; } @Bean public RabbitTemplate rabbitTemplate() throws Exception { return new RabbitTemplate(connectionFactory()); } @Bean public Queue queue() { return new Queue(QUEUE_NAME); } @Bean public TopicExchange exchange() { return new TopicExchange(EXCHANGE_NAME); } @Bean public Binding binding(Queue queue, TopicExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(QUEUE_NAME); } }
Escribiendo y leyendo de la cola
Para escribir en la cola deberemos hacer uso del objeto de la clase RabbitTemplate
Para leer de la cola deberemos utilizar la anotación @RabbitListener
@RabbitListener(queues = RabbitConfiguration.QUEUE_NAME) public void onMessageFromRabbitMQ(final String messageFromRabbitMQ){ LOGGER.info("{}", messageFromRabbitMQ); }
Se muestra el controlador que escribe y lee de la cola
package com.jorgehernandezramirez.spring.springboot.rabbitmq.controller; import com.jorgehernandezramirez.spring.springboot.rabbitmq.config.RabbitConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class); private static final String MESSAGE = "Message to RabbitMQ!"; @Autowired private RabbitTemplate rabbitTemplate; public TestController(){ //Para Spring } @RequestMapping("/") public String doSendMessageToRabbitMQ() { rabbitTemplate.convertAndSend(RabbitConfiguration.QUEUE_NAME, MESSAGE); return "Alive!"; } @RabbitListener(queues = RabbitConfiguration.QUEUE_NAME) public void onMessageFromRabbitMQ(final String messageFromRabbitMQ){ LOGGER.info("{}", messageFromRabbitMQ); } }
3. Testeando la aplicación
A continuación compilamos nuestros fuentes y arrancamos SpringBoot para testear nuestros controladores
Compilamos
Arrancamos la aplicación
Atacamos al controlador que inserta un mensaje en la cola
Se imprime por consola.
Message to RabbitMQ!