Integrating RabbitMQ with Spring Boot: Configuration, Message Production, Consumption, and Reliability
This article explains how to integrate RabbitMQ into a Spring Boot application, covering dependency setup, connection configuration, message sending and receiving, handling complex JSON messages, and ensuring both publishing and consumption reliability through confirmations, callbacks, and QoS settings.
1. Introduction
Message middleware is commonly used in system development for asynchronous processing, decoupling between systems, and traffic shaping. The following scenarios are considered:
How to integrate with the SpringBoot framework
How to send messages
How to send complex messages
How to guarantee the reliability of sending messages
How to consume messages
How to guarantee the reliability of consuming messages
How to ensure consumer scalability
How to use consumers for traffic shaping
The article uses RabbitMQ as the example message middleware.
2. Integration with SpringBoot
2.1 Add Dependency
Adding the Spring Boot starter for AMQP makes the integration straightforward.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>2.2 Add MQ Service Configuration
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: boot-example2.3 Inject Message Template
@Autowired
private RabbitTemplate rabbitTemplate;2.4 Send Message
public void sendMessage() {
rabbitTemplate.convertAndSend("test", "test", "mq produce send a message");
}2.5 Consume Message
@Component
@Slf4j
public class MqConsumer {
@RabbitListener(id = "consumerMessage1", queues = "test")
public void consumeMessage1(Message message, Channel channel, String content) {
log.info("receive message1 :{}", content);
}
}3. How to Send Complex Messages
When systems exchange complex objects as JSON, a message converter must be configured for serialization and deserialization.
3.1 Producer Sets Message Converter
@Bean
public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate();
configurer.configure(rabbitTemplate, connectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}3.2 Consumer Sets Message Converter
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
return factory;
}3.3 Consumer Specifies Listener Container Factory
@RabbitListener(queues = "test3", containerFactory = "rabbitListenerContainerFactory")
public void consumeComplexMessage(Order order) {
log.info("receive complex message:{}", order);
}4. Message Sending Reliability
4.1 Why Ensure Sending Reliability
A RabbitMQ node can lose persistent messages if it fails before the messages are written to disk. If the publisher's channel is in confirm mode, the publisher will not receive an ack for the lost message.
Therefore, enabling publisher confirms guarantees that a message is persisted before the broker acknowledges it.
4.2 How to Ensure Sending Reliability
4.2.1 Add Configuration
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true4.2.2 Specify Callback Functions
Implement RabbitTemplate.ConfirmCallback and RabbitTemplate.ReturnCallback interfaces.
@Configuration
@Slf4j
public class MqConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
/** Message server returns basic.ack */
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
log.info("receive ack confirm:{} from broker server", ack);
}
/** Message server returns basic.return */
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.error("receive return message:{} from broker server,reply code:{},reply text:{},exchange:{},routing key:{}",
message.toString(), replyCode, replyText, exchange, routingKey);
}
@Bean
public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate();
configurer.configure(rabbitTemplate, connectionFactory);
rabbitTemplate.setReturnCallback(this);
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
}4.2.3 confirm and returnedMessage
For unroutable messages, the broker first sends basic.return and then basic.ack. Therefore, both callbacks are needed to fully guarantee reliability when routing may fail.
5. Message Consumption Reliability
5.1 Why Ensure Consumption Reliability
When a node delivers a message to a consumer, it must decide whether the message is considered handled. Manual acknowledgements allow the broker to retain the message until the consumer explicitly acknowledges it, preventing loss due to connection or consumer failures.
By using manual acknowledgements, the broker only removes a message after receiving a positive ack.
5.2 How to Ensure Consumption Reliability
Official example with manual ack:
boolean autoAck = false; // set autoAck to false
channel.basicConsume(queueName, autoAck, "a-consumer-tag",
new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body)
throws IOException {
long deliveryTag = envelope.getDeliveryTag();
// negatively acknowledge, the message will be discarded
channel.basicReject(deliveryTag, false);
}
});In SpringBoot, the default listener mode already provides reliable consumption; the acknowledgement mode can be configured as needed.
6. Ensuring Consumer Scalability
When multiple consumers share a queue, the broker distributes messages in a round‑robin fashion. Adding more consumer instances increases overall consumption capacity, giving the system natural horizontal scalability.
7. Using Consumers for Traffic Shaping
To prevent a consumer from being overwhelmed, set a prefetch count (QoS) so the broker limits the number of unacknowledged messages per channel.
Setting a "prefetch count" defines the maximum number of unacknowledged deliveries permitted on a channel. Once the limit is reached, the broker stops delivering more messages until some are acknowledged.
Thus, basic.qos implements traffic shaping on the consumer side.
8. References
Consumer Acknowledgements and Publisher Confirms
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
