Building a RabbitMQ Publisher with Spring Boot
Contents
- Introduction
- Prerequisites
- Step 1: Create a Spring Boot Project
- Step 2: Define the Order Model
- Step 3: Configure RabbitMQ
- Step 4: Create the Publisher Service
- Step 5: Add a REST Controller
- Testing the Publisher
- Understanding What's Happening Behind the Scenes
- Next Up: Building a Consumer and Understanding Exchanges
Introduction
In my previous post, we explored the fundamental differences between HTTP request-response communication and event-driven architecture using RabbitMQ. Now that we understand why message brokers are valuable for building resilient, decoupled systems, let's get practical and build our first component: a Spring Boot application that publishes messages to RabbitMQ.
This publisher will represent an e-commerce storefront that sends order information to a message queue when a customer makes a purchase. By the end of this tutorial, you'll have a working publisher application and a clear understanding of how messages flow through RabbitMQ.
If you prefer a video tutorial you can find all 3 parts of this series in this YouTube video
Prerequisites
Before we start, make sure you have:
- Java and Maven installed
- A basic understanding of Spring Boot
- Docker installed (for running RabbitMQ)
- RabbitMQ running locally (using the command from the previous post)
Step 1: Create a Spring Boot Project
Start by creating a new Spring Boot project. You can use Spring Initializer (https://start.spring.io/) with the following settings:
- Project: Maven
- Language: Java
- Spring Boot: Latest stable version
- Dependencies:
- Spring for RabbitMQ
- Spring Web (for our REST controller)
- Lombok (optional, but makes our code cleaner)
Once downloaded, unzip the project and open it in your favorite IDE.
Step 2: Define the Order Model
First, let's create a model class that represents the orders we'll be sending to RabbitMQ:
package com.example.publisher.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor @ToString public class Order { private String id; private String product; private Date date; }
This class defines the structure of our message payload - an order with an ID, product description, and date.
Step 3: Configure RabbitMQ
Next, we need to set up the RabbitMQ configuration. Create a new class:
package com.example.publisher.config; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.amqp.core.Queue; 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 RabbitMQConfig { public static final String QUEUE = "order-queue"; @Bean public Queue orderQueue() { return new Queue(QUEUE); } @Bean public MessageConverter messageConverter() { return new Jackson2JsonMessageConverter(); } @Bean public AmqpTemplate template(ConnectionFactory connectionFactory) { RabbitTemplate template = new RabbitTemplate(connectionFactory); template.setMessageConverter(messageConverter()); return template; } }
This configuration:
- Defines a queue named "order-queue"
- Sets up a JSON message converter to transform our Java objects into JSON for sending as the message payload
- Configures a RabbitTemplate that our service will use to send messages
Step 4: Create the Publisher Service
Now, let's create a service that will publish orders to RabbitMQ:
package com.example.publisher.service; import com.example.publisher.config.RabbitMQConfig; import com.example.publisher.model.Order; import lombok.RequiredArgsConstructor; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service; import java.util.Date; import java.util.UUID; @Service @RequiredArgsConstructor public class OrderPublisher { private final RabbitTemplate rabbitTemplate; public void sendOrder(String product) { Order order = new Order(); order.setId(UUID.randomUUID().toString()); order.setProduct(product); order.setDate(new Date()); rabbitTemplate.convertAndSend(RabbitMQConfig.QUEUE, order); System.out.println("Sending order: " + order); } }
This service:
- Creates a new Order with a random UUID, the product name from the parameter, and the current date
- Uses RabbitTemplate to convert our Order to JSON and send it to the queue
- Logs the order for debugging purposes
The product
argument is a String that is passed from the REST controller after collecting it from a POST request body.
Step 5: Add a REST Controller
Finally, let's create a REST controller. You can think of this as representing a request constructed by our storefront when a user click the Buy
button and sent to our Publisher:
package com.example.publisher.controller; import com.example.publisher.service.OrderPublisher; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/orders") @RequiredArgsConstructor public class OrderController { private final OrderPublisher orderPublisher; @PostMapping public ResponseEntity<String> createOrder(@RequestBody String product) { orderPublisher.sendOrder(product); return ResponseEntity.ok("Order successfully placed"); } }
This controller:
- Listens for POST requests to the "/orders" endpoint
- Takes a product name as the request body
- Sends the product to our publisher service
- Returns a success message
Testing the Publisher
Now that we have everything set up, let's test our application:
- Run your Spring Boot application
- Send a POST request to
http://localhost:8080/orders
with a plain text body containing a product name:
curl -X POST http://localhost:8080/orders -H "Content-Type: text/plain" -d "Product 1"
- Check your Publisher application logs - you should see the order being sent
- Open the RabbitMQ management UI at
http://localhost:15672
and log in with guest/guest - Navigate to the "Queues" tab - you should see your order-queue with a message count
- Click on the queue, then click "Get messages" to view the message content
Congratulations! You've successfully built a Spring Boot application that publishes messages to RabbitMQ.
Understanding What's Happening Behind the Scenes
While it looks like we're sending messages directly to a queue, there's more happening behind the scenes. RabbitMQ actually uses a component called an "exchange" to route messages to queues.
In our example, we're implicitly using the default exchange, which automatically routes messages to queues with matching names. In the next post, we'll explore exchanges in more detail and build a consumer application to complete our system.
Next Up: Building a Consumer and Understanding Exchanges
In the final post of this series, we'll build a Spring Boot consumer that reads messages from our queue. We'll also dive deeper into RabbitMQ exchanges and explore how to route different types of messages to different queues.
Stay tuned!
This post is part 2 of a 3-part series on getting started with RabbitMQ and Spring Boot.