Home/Learn/RabbitMQ/@RabbitListener

@RabbitListener

Intermediate
Spring AMQP

@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.

Java — @RabbitListener variants
// 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.

Java — @QueueBinding inline declaration with DLX
@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.

Java + Properties — concurrency and error handling
// 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 Aria
1

How does @RabbitListener deserialise incoming messages?

EasyInfosys
2

What is the difference between AUTO and MANUAL ack mode in @RabbitListener?

MediumAmazon
3

How do you configure multiple consumer threads for a @RabbitListener?

MediumWipro
4

How would you send a message to a dead-letter queue when processing fails?

HardNetflix
5

What happens to a message if a @RabbitListener method throws an exception in AUTO ack mode?

MediumPivotal

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.

Loading discussion…