Spring AMQP — Cheat Sheet
RabbitMQ · 4 topics. Download the PDF or the Instagram carousel and share it.
Cheat Sheet · AiCanCode.org
Spring AMQP
RabbitMQ4 topicsQuick revision reference
1
RabbitMQ with Spring AMQP
spring-boot-starter-amqp auto-configures RabbitTemplate and a SimpleMessageListenerContainer; declare Exchanges, Queues, and Bindings as Spring beans.
- ✓spring-boot-starter-amqp auto-configures ConnectionFactory, RabbitTemplate, and listener container factory
- ✓Declare Exchange, Queue, Binding as Spring beans — RabbitAdmin creates them on the broker at startup
- ✓Jackson2JsonMessageConverter enables POJO-based send/receive without manual serialisation
- ✓@RabbitListener binds a method to a queue; return value is sent to reply-to if present
- ✓Set AcknowledgeMode.MANUAL and inject Channel + DELIVERY_TAG header for fine-grained ack control
- ✓Use RetryInterceptorBuilder on the container factory for automatic retry with backoff before DLX
Spring AMQP — topology as Spring beans
@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();
}
}2
@RabbitListener
@RabbitListener binds a method to a queue and deserialises the message automatically; supports batching, reply-to, and customisable error handlers with MessageRecoverer.
- ✓@RabbitListener creates a message listener container that polls queues with one or more consumer threads.
- ✓Method parameter type drives deserialization — requires a matching MessageConverter bean.
- ✓@Header injects AMQP message header values into method parameters.
- ✓ackMode=MANUAL gives full control over ack/nack; default is AUTO (ack on return).
- ✓@QueueBinding declares exchange, queue, and binding inline — convenient but @Bean config is cleaner.
- ✓concurrency and maxConcurrency control the thread pool size per listener container.
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
}
}
}3
RabbitTemplate
RabbitTemplate provides convertAndSend, convertSendAndReceive (synchronous RPC), and receive/receiveAndConvert for flexible produce/consume operations.
- ✓Use Jackson2JsonMessageConverter bean to enable JSON serialisation — default SimpleMessageConverter uses Java serialisation
- ✓convertAndSend is fire-and-forget; convertSendAndReceive blocks until a reply arrives (synchronous RPC over AMQP)
- ✓MessagePostProcessor lambda in convertAndSend allows setting headers, TTL, priority, and correlation ID per message
- ✓Publisher confirms verify broker acceptance; mandatory flag returns unroutable messages via callback
- ✓RabbitTemplate is thread-safe — use as a singleton; do not create per-request instances
- ✓For async RPC, use AsyncRabbitTemplate which returns CompletableFuture instead of blocking
Java — RabbitTemplate configuration and convertAndSend patterns
// Bean configuration — use Jackson for JSON serialisation
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
template.setMessageConverter(converter);
template.setExchange("orders"); // default exchange
template.setRoutingKey("order.placed"); // default routing key
return template;
}
// Fire-and-forget publishing
@Service
public class OrderEventPublisher {
private final RabbitTemplate rabbitTemplate;
// Simple: uses default exchange and routing key from bean config
public void publishOrderPlaced(OrderPlacedEvent event) {
rabbitTemplate.convertAndSend(event);
}
// Explicit exchange + routing key
public void publishOrderShipped(OrderShippedEvent event) {
rabbitTemplate.convertAndSend("orders", "order.shipped", event);
}
// With MessagePostProcessor — set custom headers
public void publishWithHeaders(OrderEvent event, String correlationId) {
rabbitTemplate.convertAndSend("orders", "order.placed", event, msg -> {
msg.getMessageProperties().setCorrelationId(correlationId);
msg.getMessageProperties().setHeader("X-Source", "order-service");
msg.getMessageProperties().setExpiration("30000"); // 30s TTL
return msg;
});
}
}4
Spring Retry with RabbitMQ
Configure a RetryInterceptorBuilder on the listener container to automatically retry failed messages with back-off before routing to a DLQ.
- ✓Spring Retry interceptor on the listener container provides in-process retries before routing to DLQ
- ✓RejectAndDontRequeueRecoverer nacks the message after exhausted retries → broker routes to Dead Letter Queue
- ✓RepublishMessageRecoverer publishes to a specific error exchange with stack trace headers — useful for structured DLQ analysis
- ✓Exponential back-off (1s, 2s, 4s) prevents hammering a struggling downstream service with rapid retries
- ✓In-process retry is for transient errors (seconds); DLQ + TTL queue loop is for longer retry delays (minutes/hours)
- ✓ImmediateRequeueMessageRecoverer requeues immediately — dangerous, can cause infinite hot loops on non-transient errors
Java — RetryInterceptorBuilder with exponential back-off and DLQ fallback
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
// Listener container factory with retry + exponential back-off
@Bean
public SimpleRabbitListenerContainerFactory retryListenerContainerFactory(
ConnectionFactory connectionFactory,
MessageConverter messageConverter) {
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(messageConverter);
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); // manual ack
// Exponential back-off retry: 1s, 2s, 4s, 8s — then send to DLQ
RetryInterceptorBuilder<?> retryBuilder = RetryInterceptorBuilder.stateless()
.maxAttempts(4)
.backOffOptions(1000, 2.0, 8000) // initialInterval, multiplier, maxInterval
.recoverer(new RejectAndDontRequeueRecoverer());
// After 4 attempts: NACK with requeue=false → message goes to DLQ
factory.setAdviceChain(retryBuilder.build());
return factory;
}
// Listener — exceptions trigger retry automatically
@RabbitListener(queues = "order.processing",
containerFactory = "retryListenerContainerFactory")
public void processOrder(OrderMessage order) {
// If this throws, Spring Retry catches it and retries
// After maxAttempts: RejectAndDontRequeueRecoverer sends to DLQ
orderService.process(order);
}Learn this free with Aria, your AI tutor → AiCanCode.org/learn/rabbitmq