Integración de RabbitMQ con Spring

1
20988

En este tutorial se explica cómo integrar RabbitMQ con Spring.

Índice de contenidos

1. Introducción

En su tutorial Implementación de Emisor y Receptor básicos con RabbitMQ, José Luis explicó los conceptos básicos de RabbitMQ. En este tutorial, lo que vamos a hacer es mostrar cómo se integra RabbitMQ en un proyecto Spring con Spring Boot.

2. Entorno

Este tutorial se ha desarrollado en el siguiente entorno:

  • Hardware: portátil MacBook Pro (15′, mediados 2010).
  • Sistema operativo: Mac OS X Yosemite 10.10.5.
  • IDE: IntelliJ IDEA 14 Ultimate.
  • Versión de Java: 1.8.0_60

3. Servidor de RabbitMQ

Empezamos instalando el servidor de RabbitMQ. Lo descargamos de aquí o, si utilizamos Mac, de aquí o a través de Homebrew:

$ brew install rabbitmq

Ahora queremos ejecutar el script rabbitmq-server. Si has descargado RabbitMQ manualmente, se encontrará en «rabbitmq_server-x.y.z/sbin/». Si lo has instalado con Homebrew en Mac, la ruta será «/usr/local/Cellar/rabbitmq/x.y.z/sbin/». En todo caso, podemos añadir al path la ruta de esta carpeta para poder ejecutar rabbitmq-server desde cualquier directorio en la terminal, en lugar de tener que ir hasta «sbin/».

Arrancamos el servidor de RabbitMQ:

$ rabbitmq-server

y nos saldrá:

          RabbitMQ x.y.z. Copyright (C) 2007-2015 Pivotal Software, Inc.
##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
##  ##
##########  Logs: /usr/local/var/log/rabbitmq/rabbit@localhost.log
######  ##        /usr/local/var/log/rabbitmq/rabbit@localhost-sasl.log
##########
          Starting broker... completed with 10 plugins.

4. Creación del proyecto en IntelliJ IDEA

Lo primero que vamos a hacer es crear un proyecto Spring Boot. Spring Boot nos sirve para crear y ejecutar aplicaciones Spring de una manera más sencilla.

En nuestro caso, empleamos IntelliJ IDEA como IDE. Seguimos los pasos mostrados en las capturas de pantalla:

rabbitmq_spring_crear_proyecto_1

rabbitmq_spring_crear_proyecto_2

rabbitmq_spring_crear_proyecto_3

rabbitmq_spring_crear_proyecto_4

Tras crear el proyecto nos saldrá un mensaje pidiendo que añadamos el pom.xml como proyecto Maven.

rabbitmq_spring_pom_1

Este mensaje también lo podemos ver si hacemos clic en la parte inferior izquierda del IDE.

rabbitmq_spring_pom_2

Lo añadimos y esperamos a que IntelliJ sincronice automáticamente las dependencias.

En este momento ya tenemos una aplicación que se puede ejecutar (el método main usa SpringApplication.run para ejecutarla). Lo comprobamos haciendo clic derecho en el archivo TutorialRabbitmqSpringApplication.java y dándole a «Run / TutorialRabbitmqSpringApplication».

rabbitmq_spring_ejecutar

El archivo pom.xml lo modificamos para dejarlo de la siguiente manera:



	4.0.0

	tutoriales.rabbitmq.spring
	tutorial-rabbitmq-spring
	0.0.1-SNAPSHOT
	jar

	tutorial-rabbitmq-spring
	RabbitMQ con Spring

	
		org.springframework.boot
		spring-boot-starter-parent
		1.2.6.RELEASE
		 
	

	
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-amqp
			1.2.6.RELEASE
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	

5. Implementación

El proyecto va a constar de tres clases: TutorialRabbitmqSpringApplication, Receiver y RabbitMqConfig. El código de ejemplo está en este repositorio de GitHub.

Receiver.java
package tutoriales.rabbitmq.spring;

public class Receiver {

    public static final String RECEIVE_METHOD_NAME = "receiveMessage";

    public void receiveMessage(String message) {
        System.out.println("[Receiver] ha recibido el mensaje \"" + message + '"');
    }
}

Receiver simplemente se encarga de imprimir el mensaje recibido.

RabbitMqConfig.java
package tutoriales.rabbitmq.spring;

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.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMqConfig {

    public static final String EXCHANGE_NAME = "exchange_name";
    public static final String ROUTING_KEY = "routing_key";

    private static final String QUEUE_NAME = "queue_name";
    private static final boolean IS_DURABLE_QUEUE = false;

    @Bean
    Queue queue() {
        return new Queue(QUEUE_NAME, IS_DURABLE_QUEUE);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange(EXCHANGE_NAME);
    }

    @Bean
    Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
    }

    @Bean
    SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(QUEUE_NAME);
        container.setMessageListener(listenerAdapter);
        return container;
    }

    @Bean
    Receiver receiver() {
        return new Receiver();
    }

    @Bean
    MessageListenerAdapter listenerAdapter(Receiver receiver) {
        return new MessageListenerAdapter(receiver, Receiver.RECEIVE_METHOD_NAME);
    }
}

La clase RabbitMqConfig viene anotada con @Configuration para indicar a Spring que contendrá definiciones de beans, los cuales son aquellos métodos que están anotados con @Bean. Vamos a ver para qué sirve cada uno:

@Bean
Queue queue() {
    return new Queue(QUEUE_NAME, IS_DURABLE_QUEUE);
}

Crea una cola a la que le otorga un nombre y le define su durabilidad.

@Bean
TopicExchange exchange() {
    return new TopicExchange(EXCHANGE_NAME);
}

Crea un exchange de tipo topic y le asigna un nombre.

@Bean
Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
}

Enlaza una cola con un exchange de tipo topic. Con with se define la clave del enlace.

@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
    final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueueNames(QUEUE_NAME);
    container.setMessageListener(listenerAdapter);
    return container;
}

Contenedor en el que se indican quiénes son los consumidores de las colas.

@Bean
Receiver receiver() {
    return new Receiver();
}

Receptor del mensaje.

@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
    return new MessageListenerAdapter(receiver, Receiver.RECEIVE_METHOD_NAME);
}

Adaptador para indicar quién recibe el mensaje y qué método lo procesa.

Nota: si te aparece el aviso de que el contexto de la aplicación no está configurado para RabbitMqConfig, como se ve en la siguiente imagen:

rabbitmq_spring_warning_1

entonces deberás ir a «File / Project Structure… / Project Settings / Modules»:

rabbitmq_spring_warning_2

hacer clic derecho en «tutorial-rabbitmq-spring», «Add / Spring»:

rabbitmq_spring_warning_3

y seguir estos pasos:

rabbitmq_spring_warning_4

rabbitmq_spring_warning_5

rabbitmq_spring_warning_6

TutorialRabbitmqSpringApplication.java
package tutoriales.rabbitmq.spring;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TutorialRabbitmqSpringApplication implements CommandLineRunner {

    private static final String MESSAGE = "Hello world!";

    @Autowired
    RabbitTemplate rabbitTemplate;

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

    @Override
    public void run(String... args) throws InterruptedException {
        System.out.println("[Application] Enviando el mensaje \"" + MESSAGE + "\"...");
        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, RabbitMqConfig.ROUTING_KEY, MESSAGE);
    }
}

La clase TutorialRabbitmqSpringApplication está anotada con @SpringBootApplication. Esta anotación, propia de Spring Boot, equivale a añadir las siguientes:

  • @Configuration. Indica que contiene beans.
  • @EnableAutoConfiguration. Activa la autoconfiguración del contexto de aplicación de Spring para que busque los beans que se van a necesitar.
  • @ComponentScan. Dice a Spring que busque componentes, configuraciones y servicios en el paquete de la clase.

Con la anotación @Autowired, incluimos el bean RabbitTemplate que nos proporciona Spring. En concreto, este template nos ayuda a enviar y recibir mensajes de una manera realmente sencilla: a través del método convertAndSend indicamos que queremos enviar el mensaje MESSAGE a las colas que tengan un enlace al exchange EXCHANGE_NAME con clave ROUTING_KEY.

5.1. Configuración de RabbitMQ

La conexión con el servidor de RabbitMQ se puede configurar a través del archivo application.properties, que admite las siguientes propiedades:

application.properties
# RabbitMQ properties
spring.rabbitmq.host=
spring.rabbitmq.port=
spring.rabbitmq.addresses=
spring.rabbitmq.username=
spring.rabbitmq.password=
spring.rabbitmq.virtual-host=
spring.rabbitmq.dynamic=

Si se omiten, por defecto tomará: localhost, el puerto 5672, el usuario guest, la contraseña guest y el host virtual /.

6. Ejecución

Lo primero es ejecutar el servidor de RabbitMQ con rabbitmq-server si no lo hemos hecho antes. Entonces ya podremos iniciar la aplicación.

Por consola, además de la salida propia de Spring Boot, deberá aparecer:

[Application] Enviando el mensaje "Hello world!"...
[Receiver] ha recibido el mensaje "Hello world!"

7. Conclusiones

La integración de RabbitMQ con Spring no tiene ninguna dificultad, pues en un rato hemos sido capaces de crear desde cero un proyecto que se sirve del framework Spring para enviar mensajes a través de RabbitMQ.

8. Referencias

Javier Sánchez Alonso
Consultor tecnológico de desarrollo de proyectos informáticos. Graduado en Ingeniería Informática y en Matemáticas en la Universidad Autónoma de Madrid. Puedes encontrarme en Autentia: ofrecemos servicios de soporte a desarrollo, factoría y formación. Somos expertos en Java/Java EE.

1 COMENTARIO

  1. Hola el ejemplo mostrado está interesante pero veo que envía como el que recibe el mensaje son parte de la misma solución.

    Si yo quisiera hacer que el mensaje sea enviado por ejemplo desde un servicio y en ese momento haga PUT del mensaje en el RabbitServer, y dicho mensaje sea obtenido desde otro servicio, como podría adaptar esta solución.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad