RabbitMQ with Spring AMQP
Intermediatespring-boot-starter-amqp auto-configures RabbitTemplate and a SimpleMessageListenerContainer; declare Exchanges, Queues, and Bindings as Spring beans.
Overview
Spring AMQP is the Spring abstraction layer over the RabbitMQ Java client. Adding `spring-boot-starter-amqp` to your project auto-configures three key beans: `ConnectionFactory` (connection pool to the broker), `RabbitTemplate` (synchronous send/receive), and `SimpleRabbitListenerContainerFactory` (container that drives `@RabbitListener` consumers). Infrastructure — exchanges, queues, and bindings — is declared as Spring beans of type `Exchange`, `Queue`, and `Binding`; Spring AMQP's `RabbitAdmin` creates them on the broker at startup. `@RabbitListener` turns any Spring bean method into a message consumer. `MessageConverter` (default: `SimpleMessageConverter`; common alternative: `Jackson2JsonMessageConverter`) serialises/deserialises message bodies.
Infrastructure Beans: Exchange, Queue, Binding
Declare your AMQP topology as Spring beans. `RabbitAdmin` detects all `Exchange`, `Queue`, and `Binding` beans in the context and calls the broker's declare APIs on startup. This makes topology reproducible and version-controllable.
@Configuration
class RabbitConfig {
public static final String ORDER_EXCHANGE = "orders.topic";
public static final String ORDER_QUEUE = "orders.created";
public static final String ROUTING_KEY = "order.created.#";
@Bean
TopicExchange orderExchange() {
return ExchangeBuilder.topicExchange(ORDER_EXCHANGE)
.durable(true).build();
}
@Bean
Queue orderQueue() {
return QueueBuilder.durable(ORDER_QUEUE)
.withArgument("x-dead-letter-exchange", "orders.dlx")
.build();
}
@Bean
Binding orderBinding(Queue orderQueue, TopicExchange orderExchange) {
return BindingBuilder.bind(orderQueue)
.to(orderExchange)
.with(ROUTING_KEY);
}
// JSON message converter — auto-registered if only one is present
@Bean
MessageConverter jacksonConverter() {
return new Jackson2JsonMessageConverter();
}
}Sending and Receiving with RabbitTemplate
`RabbitTemplate.convertAndSend()` serialises the payload with the configured `MessageConverter` and publishes it. `@RabbitListener` binds a method to one or more queues. Return values are automatically sent to the `reply-to` queue if present, enabling RPC.
// Producer
@Service
@RequiredArgsConstructor
class OrderPublisher {
private final RabbitTemplate rabbit;
public void publish(OrderCreatedEvent event) {
rabbit.convertAndSend(
RabbitConfig.ORDER_EXCHANGE,
"order.created.eu", // routing key
event // serialised by Jackson2JsonMessageConverter
);
}
}
// Consumer
@Component
class OrderConsumer {
@RabbitListener(queues = RabbitConfig.ORDER_QUEUE,
containerFactory = "rabbitListenerContainerFactory")
public void handle(OrderCreatedEvent event, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
try {
processOrder(event);
channel.basicAck(tag, false);
} catch (RecoverableException e) {
channel.basicNack(tag, false, true); // requeue
} catch (Exception e) {
channel.basicNack(tag, false, false); // → DLX
}
}
}Container Configuration: Concurrency & Error Handling
The `SimpleRabbitListenerContainerFactory` controls concurrency, prefetch, ack-mode, and error handling. `DirectMessageListenerContainer` (lower latency, one channel per consumer) is an alternative for high-concurrency scenarios. Attach a `MessageRecoverer` or `RetryInterceptor` to the factory for automatic retry before sending to the DLX.
@Bean
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory cf, MessageConverter converter) {
var factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cf);
factory.setMessageConverter(converter);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setPrefetchCount(10);
factory.setConcurrentConsumers(3);
factory.setMaxConcurrentConsumers(10); // auto-scale consumers
// Retry up to 3 times with exponential backoff, then send to DLX
factory.setAdviceChain(RetryInterceptorBuilder.stateless()
.maxAttempts(3)
.backOffOptions(500, 2.0, 5_000)
.recoverer(new RejectAndDontRequeueRecoverer())
.build());
return factory;
}Key Points to Remember
- 1spring-boot-starter-amqp auto-configures ConnectionFactory, RabbitTemplate, and listener container factory
- 2Declare Exchange, Queue, Binding as Spring beans — RabbitAdmin creates them on the broker at startup
- 3Jackson2JsonMessageConverter enables POJO-based send/receive without manual serialisation
- 4@RabbitListener binds a method to a queue; return value is sent to reply-to if present
- 5Set AcknowledgeMode.MANUAL and inject Channel + DELIVERY_TAG header for fine-grained ack control
- 6Use RetryInterceptorBuilder on the container factory for automatic retry with backoff before DLX
Interview Questions
Sign in to ask AriaWhat does spring-boot-starter-amqp auto-configure?
How does RabbitAdmin know which exchanges and queues to create on the broker?
What is the difference between SimpleMessageListenerContainer and DirectMessageListenerContainer?
How would you configure automatic retry with exponential backoff for a @RabbitListener?
How do you switch from the default SimpleMessageConverter to Jackson-based JSON conversion?
Ask Aria about RabbitMQ with Spring AMQP
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.