1. Introduction
With Spring Boot Framework’s comprehensive RabbitMQ support, code-savvy developers can quickly get their message out to the world! Defining broker resources has never been more accessible with its programmatically defined application beans available automatically on startup. Customize away: Annotations provide unparalleled control over settings – see for yourself by trying your hand at creating a Spring AMQP publisher today!
2. Prerequisites and Setup
You may skip this section if you do not follow this tutorial thoroughly and only want to look at code examples.
In case you are feeling baffled by RabbitMQ? I understand–it’s easy to get tangled up in tech talk. Don’t stress, though: a quick read about RabbitMQ architecture will make you hop ahead confidently!
Also, Suppose you try to follow this tutorial using your IDE. In that case, I will assume you already have a RabbitMQ message broker running in the docker. In case you don’t, here is RabbitMQ running in Docker.
2.1. Generate Project Template
Next, we generate a blank Spring Boot application template using Spring Initializr with all the required dependencies. Click generate and import into your IDE.
2.2. Add Project Configuration
Let’s define RabbitMQ resources via Spring Beans. The configuration class contains a topic exchange and a queue bound together using a binding key. We need to establish the connection to the broker via the connection factory to ensure that defined beans are created automatically on application startup.
@Configuration public class RabbitConfiguration { public static final String USERS_EXCHANGE = "users.exchange"; public static final String USERS_QUEUE = "users.queue"; public static final String USERS_ROUTING_KEY = "users"; @Bean ApplicationRunner runner(ConnectionFactory connectionFactory) { return args -> connectionFactory.createConnection().close(); } @Bean TopicExchange usersExchange() { return new TopicExchange(USERS_EXCHANGE); } @Bean Queue usersQueue() { return QueueBuilder.durable(USERS_QUEUE) .build(); } @Bean Binding bindingUsers() { return BindingBuilder .bind(usersQueue()) .to(usersExchange()) .with(USERS_ROUTING_KEY); } }
3 What is a Publisher Application?
RabbitMQ’s producer application offers a user-friendly solution for managing messaging queues, giving you ultimate control over how your messages are routed using the routing key.
By receiving and routing messages from multiple sources to a default exchange as its primary hub of message flow, a producer app is a powerful tool that prioritizes and organizes all incoming data – allowing you to maximize your RabbitMQ server infrastructure.
RabbitMQ offers four different types of exchanges, each with a different purpose and works distinctly.
3. Spring AMQP Publisher – Publish String Message
To publish messages using Spring AMQP, we can rely on the autoconfiguration of the RabbitMQ broker, and we don’t need to worry about defining our connection management.
Let’s create a UsersProducer component with RabbitTemplate to send messages using the routing key to the broker. RabbitTemplate helper class is available with the Spring AMQP library.
@Log4j2 @Component public class UsersProducer { private final RabbitTemplate rabbitTemplate; public UsersProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void publishStringMessage(String message) { log.info("About to publish message: {}", message); rabbitTemplate.convertAndSend( RabbitConfiguration.USERS_EXCHANGE, RabbitConfiguration.USERS_ROUTING_KEY, message ); } }
We have also created a rest endpoint using the producer class to publish messages to the topic exchange in the RabbitMQ server.
@RestController @RequestMapping("/users/v1") public class UsersController { private final UsersProducer producer; public UsersController(UsersProducer producer) { this.producer = producer; } @PostMapping("/add") public ResponseEntity<String> sendMessage( @RequestBody String message) { producer.publishStringMessage(message); return ResponseEntity.ok().build(); } }
Start the application and ensure that the resources from RabbitConfiguration configuration class are created in the RabbitMQ management console (http://localhost:15672/) in the exchanges and queues tabs.
Let’s send a request with a test message published with users routing key to the above endpoint using any command line tool or Postman. I will use bash and curl to execute the following command.
curl --request POST -H "Content-Type: application/json" -d '{"id":1,"name":"Tom","email":"tom12@gmail.com"}' http://localhost:8080/users/v1/add
We can verify that published messages exist in the users.queue by going to the management console queues page tab and clicking on the created queue. There we have a view similar to the one below:
4. Spring AMQP Publisher – Publish Custom Object
The message converted converts Java Object to Spring AMQP message type. To publish custom objects, we need to override the custom converted.
The SimpleMessageConverter is limited to Strings, byte arrays and serializable payloads. The application throws an exception without a custom message converter because it cannot convert the message.
To do this, we need to define two Spring beans inside our RabbitConfiguration, first a new message converter and second with a rabbit template that will use it. The Jackson2JsonMessageConverter will serialize the Java object to a JSON format.
@Bean RabbitTemplate rabbitTemplate( ConnectionFactory connectionFactory, MessageConverter messageConverter) { RabbitTemplate rabbitTemplate = new RabbitTemplate(); rabbitTemplate.setConnectionFactory(connectionFactory); rabbitTemplate.setMessageConverter(messageConverter); return rabbitTemplate; } @Bean MessageConverter messageConverter() { return new Jackson2JsonMessageConverter(); }
This time in the producer class, we are passing the OldFormatUser object.
@Log4j2 @Component public class UsersProducer { private final RabbitTemplate rabbitTemplate; public UsersProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void publishStringMessage(OldFormatUser user) { log.info("About to publish message: {}", user); rabbitTemplate.convertAndSend( RabbitConfiguration.USERS_EXCHANGE, RabbitConfiguration.USERS_ROUTING_KEY, user ); } }
Restart the application and send the same message with users routing key just like before. However, here we use a custom Java object serialized into JSON instead of raw String. Verify on the management portal that the expected returned message exists in the queue.
curl --request POST -H "Content-Type: application/json" -d '{"id":1,"name":"Tom","email":"tom12@gmail.com"}' http://localhost:8080/users/v1/add
5. Publisher Confirms
RabbitMQ’s Publisher Confirmation feature provides you with an extra level of assurance when it comes to message delivery. If enabled, the broker will send a receipt verifying that the consumer has accepted or forwarded the message to another queue.
RabbitMQ’s publisher confirmation assures that the server sends and receives messages. This makes possible reliable messaging while safeguarding against any lost communication.
When enabled, broker responses specify message acknowledgement; this ensures successful handling on the server and offers a protocol to take action when not confirmed.
6. Summary
This article has looked at how to publish messages using Spring AMQP Publisher. Spring Boot integration with RabbitMQ makes sharing messages easy and customizable. After all, it’s all in the details! With the Spring Boot framework, you can use pre-set message converters for basic types or customise a converter tailored to your needs – ensuring every message is delivered just how you want it.
Daniel Barczak
Daniel Barczak is a software developer with a solid 9-year track record in the industry. Outside the office, Daniel is passionate about home automation. He dedicates his free time to tinkering with the latest smart home technologies and engaging in DIY projects that enhance and automate the functionality of living spaces, reflecting his enthusiasm and passion for smart home solutions.
Leave a Reply