@RabbitListener
Intermediate@RabbitListener binds a method to a queue and deserialises the message automatically; supports batching, reply-to, and customisable error handlers with MessageRecoverer.
Overview
@RabbitListener is the Spring AMQP annotation for binding a bean method to one or more queues. Spring creates a SimpleMessageListenerContainer (or DirectMessageListenerContainer) under the hood. It handles message deserialization via the configured MessageConverter, concurrency (multiple consumer threads), error handling (ErrorHandler, MessageRecoverer), and the acknowledgement lifecycle. @RabbitListener supports binding at the method or class level and can declare queues inline via @QueueBinding.
@RabbitListener Fundamentals
Annotate any Spring-managed method with @RabbitListener to consume messages. The method parameter type drives deserialization. Add @Header to extract AMQP headers and Acknowledgment for manual ack.
// Basic listener — auto-deserialized via MessageConverter
@Component
public class OrderConsumer {
// Single queue
@RabbitListener(queues = "order-processor")
public void onOrder(OrderEvent event) {
orderService.process(event); // auto-ack on return
}
// Multiple queues
@RabbitListener(queues = { "orders.uk", "orders.eu" })
public void onRegionalOrder(OrderEvent event,
@Header("region") String region) {
orderService.processForRegion(event, region);
}
// Access raw message
@RabbitListener(queues = "raw-messages")
public void onRawMessage(Message message) {
byte[] body = message.getBody();
MessageProperties props = message.getMessageProperties();
log.info("Received {} bytes, content-type={}", body.length, props.getContentType());
}
// Manual acknowledgement
@RabbitListener(queues = "critical-orders",
ackMode = "MANUAL")
public void onCritical(OrderEvent event, Acknowledgment ack) {
try {
orderService.processCritical(event);
ack.acknowledge();
} catch (Exception e) {
ack.nack(false); // nack, don't requeue → goes to DLX
}
}
}Inline Queue Declaration with @QueueBinding
@RabbitListener can declare the exchange, queue, and binding inline using @QueueBinding. This is convenient for tests and simple setups but @Bean declarations in @Configuration are preferred for production.
@Component
public class NotificationConsumer {
// Inline declaration — Spring creates exchange, queue, binding on startup
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "notifications.email", durable = "true"),
exchange = @Exchange(value = "notifications", type = ExchangeTypes.TOPIC),
key = "notification.email.*"
))
public void onEmailNotification(EmailNotification event) {
emailService.send(event);
}
// Declare a queue with DLX arguments inline
@RabbitListener(bindings = @QueueBinding(
value = @Queue(
value = "orders.processing",
durable = "true",
arguments = {
@Argument(name = "x-dead-letter-exchange", value = "orders.dlx"),
@Argument(name = "x-message-ttl", value = "60000", type = "java.lang.Integer")
}
),
exchange = @Exchange("orders"),
key = "order.placed"
))
public void onOrderPlaced(OrderEvent event) {
orderService.process(event);
}
}Concurrency & Error Handling
Set concurrency to run multiple consumer threads per listener. Configure a global ErrorHandler or per-listener containerFactory with custom error handling. Use MessageRecoverer to dead-letter or log failed messages.
// Concurrency configuration
// application.properties
spring.rabbitmq.listener.simple.prefetch=10
spring.rabbitmq.listener.simple.concurrency=3
spring.rabbitmq.listener.simple.max-concurrency=10
// Or per-listener via a custom factory
@Bean
public SimpleRabbitListenerContainerFactory criticalFactory(
ConnectionFactory cf, MessageConverter converter) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cf);
factory.setMessageConverter(converter);
factory.setConcurrentConsumers(5);
factory.setMaxConcurrentConsumers(20);
factory.setPrefetchCount(1);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setErrorHandler(t -> log.error("Listener error", t));
return factory;
}
// Use custom factory
@RabbitListener(queues = "critical-orders",
containerFactory = "criticalFactory")
public void onCritical(OrderEvent event) { ... }Key Points to Remember
- 1@RabbitListener creates a message listener container that polls queues with one or more consumer threads.
- 2Method parameter type drives deserialization — requires a matching MessageConverter bean.
- 3@Header injects AMQP message header values into method parameters.
- 4ackMode=MANUAL gives full control over ack/nack; default is AUTO (ack on return).
- 5@QueueBinding declares exchange, queue, and binding inline — convenient but @Bean config is cleaner.
- 6concurrency and maxConcurrency control the thread pool size per listener container.
Interview Questions
Sign in to ask AriaHow does @RabbitListener deserialise incoming messages?
What is the difference between AUTO and MANUAL ack mode in @RabbitListener?
How do you configure multiple consumer threads for a @RabbitListener?
How would you send a message to a dead-letter queue when processing fails?
What happens to a message if a @RabbitListener method throws an exception in AUTO ack mode?
Ask Aria about @RabbitListener
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.