Messaging Application using Rabbit MQ, Spring Boot, and Spring AMQP

malindu ruwantha
4 min readApr 25, 2023

Messaging is a secure and reliable way of exchanging information between multiple parties. In this tutorial, we will create a simple data exchange mechanism using Spring Boot, the Spring AMQP protocol, and RabbitMQ.

AMQP Protocol

AMQP provides a standardized way to send and receive messages, defining a set of patterns and an architecture that can be used for various messaging scenarios, regardless of the platform or technologies used. It also ensures reliable delivery of messages, maintaining the correct order and preventing message loss. Furthermore, AMQP provides secure communication between messaging systems. It can be implemented with messaging systems like RabbitMQ, Microsoft Azure Service Bus, and Apache Qpid, and is supported by languages such as Java, Python, and .NET.

AMQP Architecture

1. Environment setup

1.1. Create a Rabbit MQ server locally using docker

  • To pull the Docker image using the terminal, use the following command, replacing ‘3.10.5-management’ with the image name you selected:
docker pull rabbitmq:3.10.5-management

It will pull the docker image and you can verify it by going to the image tab in the docker desktop application.

  • Then you have to start the docker container. Use the following command
docker run --rm -it -p 15672:15672 -p 5672:5672 rabbitmq:3.10.5-management
  • You have now started a local RabbitMQ server. You can verify it by navigating to the RabbitMQ management console, which is up and running on port 15672. To access the console, go to http://localhost:15672/ in your web browser.
  • Default UserName and Password is guest

2. Setup Spring boot project

3. Creating the Message Producer class

application.properties

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest


rabbitmq.queue.name =simple_messaging_app
rabbitmq.exchange.name = simple-messaging-app_exchange
rabbitmq.routing.key = simple-messaging-app_routing_key

Now we need to create the configuration class to bind the queue with the relevant exchanges. Let’s create a class named RabbitMQConfig.java

package com.javaMqGuide.springbootrabbitMqproject.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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

@Value("${rabbitmq.queue.name}")
//${rabbitmq.queue.name} will get fetched from the application.properties
private String queue;

@Value("${rabbitmq.exchange.name}")
private String exchange;

@Value("${rabbitmq.routing.key}")
private String routingkey;


@Bean
public Queue queue(){
return new Queue(queue);
}


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

//binding between queue and exchange using routing key
@Bean
public Binding binding(){
return BindingBuilder.bind(queue())
.to(exchange())
.with(routingkey);
}
}

In the RabbitMQConfig class, we will create separate beans to return a queue and an exchange. The messaging queue will be bound to the exchange using a routing key.

Creating the Message Producer
RabbitMQProduser.java

package com.javaMqGuide.springbootrabbitMqproject.publisher;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class RabbitMQProducer {

@Value("${rabbitmq.exchange.name}")
private String exchange;

@Value("${rabbitmq.routing.key}")
private String routingkey;

private RabbitTemplate rabbitMqTemplate;

@Autowired
public RabbitMQProduser(RabbitTemplate rabbitMqTemplate) {
this.rabbitMqTemplate = rabbitMqTemplate;
}

public void sendMessage(String message){

rabbitMqTemplate.convertAndSend(exchange,routingkey,message);
}
}
  • {rabbitmq.routing.key} and {rabbitmq.exchange.name} will be fetched from the application.properties file

Message Producer is responsible for publishing a message to the queue.

Now, let’s create a REST controller to publish messages. This will create a REST endpoint that uses the RabbitMQProducer class to publish the messages. Let’s create a class named MessageController.java.

package com.javaMqGuide.springbootrabbitMqproject.controller;

import com.javaMqGuide.springbootrabbitMqproject.publisher.RabbitMQProduser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1")
public class MessageController {

@Autowired
private RabbitMQProduser produser;

@GetMapping("/publish")
public ResponseEntity<String> sendMessage(@RequestParam("message") String message){
produser.sendMessage(message);
return ResponseEntity.ok("Message send successfullt to RabbitMQ");

}

}

Now you can use http://localhost:8080/api/v1/publish?message=Test Message url to publish a message to the queue

To verify that the implementation is working as intended, use the RabbitMQ management console. You should see the message get queued from the console.

4. Creating the message consumer class

package com.javaMqGuide.springbootrabbitMqproject.consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

@Service
public class RabbitMQConcumer {

private static final Logger LOGGER = LoggerFactory.getLogger(RabbitMQConcumer.class);



@RabbitListener(queues = {"${rabbitmq.queue.name}"})
public void consume(String message){
LOGGER.info(String.format("Received mesage -> %s",message));


}





}

We now need to create a listener for the queue. When a message is published to the queue, the listener will be executed. You can use a logger instance to test the consumer.

--

--