Spring Boot + RabbitMQ - Producer and Consumer Example

In this section, we will learn how to do asynchronous communication using RabbitMQ in Spring Boot application.

We will develop two Spring Boot applications, one producer and one consumer application, then we will learn how to use RabbitMQ broker in the Spring boot application to send and receive messages between the Producer and the Consumer.


1. What is Message Broker?

In the digital world, different systems are constantly sending or receiving messages. This must be carried out in a controlled manner so that messages do not block each other, end up creating a jam and processes cannot function optimally. In order for applications to be able to communicate with each other easily, it makes sense to create an intermediary, that is, a service that is responsible for managing the distribution of messages: this is what is known as a messaging broker. RabbitMQ, one of the best known.


2. What is RabbitMQ?

RabbitMQ is a message broker that acts as an intermediary platform where different applications can send and receive binary data or messagesRabbitMQ originally implements the Advanced Message Queuing Protocol (AMQP). But now RabbitMQ also supports several other API protocols such as STOMP, MQTT, and HTTP.

The advantage of RabbitMQ is that the producer of the message sends it to the queue. At this point, it is the messaging broker that takes care of it, so the producer can dedicate himself to a new task without having to wait for the message to reach the consumer. With this system, the message remains in the queue and the consumer can pick it up later. By then, the producer may already be engaged in a new task. That is, it is an asynchronous communication: producers and consumers do not have to go at the same pace.


3. Spring AMQP

The Spring AMQP project applies core Spring concepts to the development of AMQP-based messaging solutions. It provides a "template" as a high-level abstraction for sending and receiving messages.

The Spring AMQP project consists of two parts; spring-amqp is the base abstraction, and spring-rabbit is the RabbitMQ implementation.

More Info - Click here!


4. What we will build?

We will develop two Spring Boot applications, one producer and one consumer application, then we will learn how to use RabbitMQ broker in the Spring boot application to send and receive messages between the Producer and the Consumer.

The following diagram is an overview of the components in our messaging system.

Four stations participate in the transmission of the messages:

  • Producer: creates the messages
  • Exchanger: delivers messages
  • Queue: stores messages
  • Consumer: processes the message

The producer publishes a message, but does not send it directly to the consumer, but delivers it to the exchanger. In this station, the messages are distributed through the queue, which serve as a reading point for a message for a consumer. Both the exchanger and the queues are part of RabbitMQ and are managed by the software. 


5. Install RabbitMQ using Docker

Assuming the Docker Desktop has been installed, we use the following command to pull a RabbitMQ Docker image from DockerHub.. 

docker pull rabbitmq:3.11-management

After the Docker image is downloaded and saved, we can start a RabbitMQ container using the following command:

docker run --rm -it -p 15672:15672 -p 5672:5672 rabbitmq:3.11-management

In the command above, port 5672 is used for the RabbitMQ client connections, and port 15672 is for the RabbitMQ management website.

Then, open a browser window and use the URL http://localhost:15672 to visit the RabbitMQ management website.

We can use default Username=guest and Password=guest to log into the RabbitMQ management website.


6. Creating spring boot consumer application

First, open the Spring initializr https://start.spring.io/ 

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact consumer. Here I selected the Maven project - language Java 17 - Spring Boot 3.0.5 and add Spring Weband Spring for RabbitMQ.

Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(consumer) file and downloads the project. Then, Extract the Zip file. 

Then, import the project on your favourite IDE.

Final Project directory:


Complete pom.xml

<?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>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</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>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-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>


application.properties

You can then configure rabbitmq properties according to the Spring Boot Documentation - scroll down to the rabbitmq properties...

Then, specify queue name, and port.

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

rabbitmq.queue.name=knfQueue
server.port=9080


Create RabbitMQ Consumer

The Consumer app will listen the queue and consume the messages from the queue. Also consumed messages will be printed to console.

package com.knf.dev.demo.consumer;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class RabbitMQConsumer {


@RabbitListener(queues = {"${rabbitmq.queue.name}"})
public void consume(String message){

System.out.println("Message arrived! Message: " + message);
}
}


Application.java

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

}


7. Creating spring boot producer application

First, open the Spring initializr https://start.spring.io/ 

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact producer. Here I selected the Maven project - language Java 17 - Spring Boot 3.0.5 and add Spring Weband Spring for RabbitMQ.

Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(producer) file and downloads the project. Then, Extract the Zip file. 

Then, import the project on your favourite IDE.

Final Project directory:


Complete pom.xml

<?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>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>producer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>producer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</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>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-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>


application.properties

Add the following configuration to application.properties file:

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

rabbitmq.queue.name=knfQueue
rabbitmq.exchange.name=knfTopicExchange
rabbitmq.routing.key=knfRoutingKey

server.port=8081


RabbitMQConfig.java

Firstly, we will implement the RabbitMQConfig class. It will handle the configuration of the RabbitMq like below.

package com.knf.dev.demo.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
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}")
private String queue;

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

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

@Bean
Queue createQueue() {

return new Queue(queue);
}

@Bean
TopicExchange exchange() {

return new TopicExchange(exchange);
}

@Bean
Binding binding(Queue queue, TopicExchange exchange) {

return BindingBuilder.bind(queue).
to(exchange).with(routingKey);
}

@Bean
SimpleMessageListenerContainer container(
ConnectionFactory connectionFactory) {

SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);

return container;
}
}


Create RabbitMQ Producer

We use RabbitTemplate to convert and send a message using RabbitMQ. 

package com.knf.dev.demo.producer;


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;

@Autowired
private RabbitTemplate rabbitTemplate;


public void sendMessage(String message){

rabbitTemplate.convertAndSend(
exchange, routingKey, message);
}
}


Create MessageController

package com.knf.dev.demo.controller;

import com.knf.dev.demo.producer.RabbitMQProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

@Autowired
private RabbitMQProducer rabbitMQProducer;

@PostMapping("/postMessage")
public String publishMessage(
@RequestParam("message") String message) {

rabbitMQProducer.sendMessage(message);
return "Message was sent successfully";
}
}


Application.java

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

}


8. Verify our system is working as expected

First start the producer application, then start the consumer application:


Run the Spring Boot application - mvn spring-boot:run


OR 


Run this Spring boot application from 

  • IntelliJ IDEA IDE by right click - Run 'Application.main()' 
  • Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.

Open a Postman or any other tool and send a message to the producer:

The console of the consumer application now prints:

Source code - click here!

Comments

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

ReactJS - Bootstrap - Buttons

Java - How to Count the Number of Occurrences of Substring in a String

Spring Boot 3 + Spring Security 6 + Thymeleaf - Registration and Login Example

Spring Core | BeanFactoryPostProcessor | Example

Custom Exception Handling in Quarkus REST API

File Upload, Download, And Delete - Azure Blob Storage + Spring Boot Example

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024