Spring Boot RabbitMQ Publisher and Consumer Example

In this tutorial, you will learn how to Spring boot application that sends and receive messages to/from the RabbitMQ server.

RabbitMQ is an open-source message broker software. It accepts messages from producers and delivers them to consumers. It acts like a middleman which can be used to reduce loads and delivery times taken by web application servers.

To exchange messages between different applications, we can use RabbitMQ as a message broker.

Producers send/publish the messages to the broker -> Consumers receive the messages from the broker. RabbitMQ acts as a communication middleware between both producers and consumers even if they run on different machines.
Learn more about RabbitMQ at How RabbitMQ Works and RabbitMQ Core Concepts

Install RabbitMQ in Windows :

  1. Download and install ERlang http://erlang.org/download/otp_win64_22.3.exe
  2. Download and install RabbitMQ https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.8/rabbitmq-server-3.8.8.exe
  3. Go to RabbitMQ Server install Directory C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.3\sbin
  4. Run command rabbitmq-plugins enable rabbitmq_management
  5. Open the browser and enter http://localhost:15672/ to redirect to RabbitMQ Dashboard
  6. Also, we can Open it with IP Address http://127.0.0.1:15672
  7. Login page default username and password is guest
  8. After successfully login, you should see the RabbitMQ Home page

Once RabbitMQ setup has been done then let's create the Spring boot application step by step. 

1. Create Spring Boot Project

We’ll use Spring initializr web tool to bootstrap our application. 

Go to http://start.spring.io

Select Java in the language section.

Enter Artifact as spring-boot-rabbitmq-example

Add WebLombokSpring for RabbitMQ dependencies.

Click Generate to generate and download the project.

Once the project is generated, unzip it and import it into your favorite IDE.

2. Maven Dependencies

Open the pom.xml file and confirm below dependencies are present:
		<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.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

3. RabbitMQ Messaging Config

Let's create a MessagingConfig class that holds all the RabbitMQ messaging related configurations:
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MessagingConfig {

    public static final String QUEUE = "demo_queue";
    public static final String EXCHANGE = "demo_exchange";
    public static final String ROUTING_KEY = "demo_routingKey";

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

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

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

    @Bean
    public MessageConverter converter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public AmqpTemplate template(ConnectionFactory connectionFactory) {
        final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(converter());
        return rabbitTemplate;
    }
}

Note that in the above configuration, we have provided hardcoded values like this:

    public static final String QUEUE = "demo_queue";
    public static final String EXCHANGE = "demo_exchange";
    public static final String ROUTING_KEY = "demo_routingKey";

You can make these fields configurable by defing them in an application.properties file.

4. Define Model Classes

Let's create few model classes to transfer between consumer and producer.

Order Class

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Order {

    private String orderId;
    private String name;
    private int qty;
    private double price;
}

OrderStatus Enum

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class OrderStatus {

    private Order order;
    private String status;//progress,completed
    private String message;
}

5. Consumer

import com.springboot.rabbitmq.demo.config.MessagingConfig;
import com.springboot.rabbitmq.demo.dto.OrderStatus;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class User {

    @RabbitListener(queues = MessagingConfig.QUEUE)
    public void consumeMessageFromQueue(OrderStatus orderStatus) {
        System.out.println("Message recieved from queue : " + orderStatus);
    }
}

6. Publisher

import com.springboot.rabbitmq.demo.config.MessagingConfig;
import com.springboot.rabbitmq.demo.dto.Order;
import com.springboot.rabbitmq.demo.dto.OrderStatus;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

@RestController
@RequestMapping("/order")
public class OrderPublisher {

    @Autowired
    private RabbitTemplate template;

    @PostMapping("/{restaurantName}")
    public String bookOrder(@RequestBody Order order, @PathVariable String restaurantName) {
        order.setOrderId(UUID.randomUUID().toString());
        //restaurantservice
        //payment service
        OrderStatus orderStatus = new OrderStatus(order, "PROCESS", "order placed succesfully in " + restaurantName);
        template.convertAndSend(MessagingConfig.EXCHANGE, MessagingConfig.ROUTING_KEY, orderStatus);
        return "Success !!";
    }
}

7. Run Spring Boot Application

We’ve successfully built all the APIs for our application. Let’s now run the app and test the APIs.

Just go to the root directory of the application and type the following command to run it -

$ mvn spring-boot:run

The application will start at Spring Boot’s default tomcat port 8080.


Comments