From spring
Build RabbitMQ or AMQP producers and consumers in Spring with RabbitTemplate, @RabbitListener, queue and exchange topology, message conversion, retry, and dead-letter handling. Use this skill when building RabbitMQ or AMQP producers and consumers in Spring with RabbitTemplate, @RabbitListener, queue and exchange topology, message conversion, listener containers, batching, retry, dead-letter handling, broker configuration, testing, observability, or stream and multi-broker variants.
npx claudepluginhub ririnto/sinon --plugin springThis skill uses the workspace's default tool permissions.
Use this skill when building RabbitMQ or AMQP producers and consumers in Spring with `RabbitTemplate`, `@RabbitListener`, queue and exchange topology, message conversion, listener containers, batching, retry, dead-letter handling, broker configuration, testing, observability, or stream and multi-broker variants.
references/async-return-listeners.mdreferences/batch-listeners.mdreferences/broker-configuration-and-vhost-setup.mdreferences/container-variants-and-concurrency.mdreferences/conversion-and-listener-method-signatures.mdreferences/delayed-exchange-and-broker-events.mdreferences/delivery-debugging-checklist.mdreferences/distributed-tracing-for-amqp.mdreferences/listener-metrics-and-micrometer.mdreferences/listener-threading-and-back-pressure.mdreferences/multi-broker-variants.mdreferences/polling-receive.mdreferences/publisher-confirms-returns-and-send-reliability.mdreferences/request-reply.mdreferences/retry-recovery-and-transactions.mdreferences/stream-variants.mdreferences/testing-support-and-listener-harnesses.mdMandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Use this skill when building RabbitMQ or AMQP producers and consumers in Spring with RabbitTemplate, @RabbitListener, queue and exchange topology, message conversion, listener containers, batching, retry, dead-letter handling, broker configuration, testing, observability, or stream and multi-broker variants.
The latest released Spring AMQP line is 4.0.3. Keep this skill on the 4.0.x stable line unless the project is intentionally evaluating the 4.1 preview line.
Use spring-amqp for RabbitMQ-oriented producers, consumers, listener containers, queue and exchange topology, delivery retries, dead-letter flows, and RabbitMQ-specific operational seams.
spring-kafka or spring-pulsar for Kafka or Pulsar semantics and client APIs.Use this map to keep the official Spring AMQP 4.x surface visible without pushing the common queue path into references/.
| Surface | Start here when | Open a reference when |
|---|---|---|
| Queue and exchange topology | The module needs explicit queue, exchange, binding, and routing-key contracts | Broker credentials or vhost setup are the blocker in references/broker-configuration-and-vhost-setup.md, or delayed exchange and broker events are the blocker in references/delayed-exchange-and-broker-events.md |
RabbitTemplate send and receive | The module publishes or performs occasional pull-style receive operations | Request-reply semantics are the blocker in references/request-reply.md, or pull-style polling receive is the blocker in references/polling-receive.md |
| Publish reliability | The producer must know whether a message was routed and accepted | Publisher confirms, returns, or mandatory publishing are the blocker in references/publisher-confirms-returns-and-send-reliability.md |
@RabbitListener consumer path | The consumer is an ordinary queue listener with one payload contract | Listener signatures, headers, validation, or conversion are the blocker in references/conversion-and-listener-method-signatures.md |
| Listener containers | One baseline container factory is enough for the first consumer | Container choice, prefetch, concurrency, or ordering tradeoffs are the blocker in references/container-variants-and-concurrency.md |
| Retry, recovery, and transactions | The listener needs one explicit exhausted-message outcome | Recoverer choice, transactional semantics, or deeper failure classification are the blocker in references/retry-recovery-and-transactions.md |
| Batching and async listeners | The consumer path is no longer one-message-in, one-message-out | Batch listeners are the blocker in references/batch-listeners.md, async returns are the blocker in references/async-return-listeners.md, polling receive is the blocker in references/polling-receive.md, or consumer threading is the blocker in references/listener-threading-and-back-pressure.md |
| Streams | Queue semantics are not enough | RabbitMQ stream plugin semantics are the blocker in references/stream-variants.md |
| Multiple brokers | One broker connection is no longer enough | Broker isolation is the blocker in references/multi-broker-variants.md |
| Testing | The contract needs broker-focused or listener-focused verification | Test harness depth is the blocker in references/testing-support-and-listener-harnesses.md |
| Observability and debugging | Delivery behavior must be measured or diagnosed in production | Listener metrics are the blocker in references/listener-metrics-and-micrometer.md, tracing is the blocker in references/distributed-tracing-for-amqp.md, or delivery diagnosis is the blocker in references/delivery-debugging-checklist.md |
The ordinary Spring AMQP job is:
RabbitTemplate and consume through @RabbitListener.Use the Boot starter for application code and the Rabbit test module for listener and broker-focused tests.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
| Need | Artifact |
|---|---|
| Ordinary publisher and listener path | spring-boot-starter-amqp |
| Listener and broker-focused tests | spring-rabbit-test |
| RabbitMQ stream semantics | stream client support from references/stream-variants.md |
./mvnw test -Dtest=OrderMessagingTests
./gradlew test --tests OrderMessagingTests
./mvnw spring-boot:run
./gradlew bootRun
Run the ordinary queue path first. Add broker confirms, request-reply, streams, or multiple brokers only after the base send/receive flow is stable.
Start with explicit queue, exchange, binding, and routing-key names. Keep the topology stable before publishers and consumers are deployed.
@Bean
Queue ordersQueue() {
return QueueBuilder.durable("orders")
.deadLetterExchange("orders.dlx")
.deadLetterRoutingKey("orders.dlq")
.build();
}
@Bean
DirectExchange ordersExchange() {
return new DirectExchange("orders.exchange");
}
@Bean
Binding ordersBinding() {
return BindingBuilder.bind(ordersQueue()).to(ordersExchange()).with("orders.created");
}
Use Spring declarations as the shared application contract. Treat queue names, exchange type, and routing keys as stable integration identifiers. Open references/broker-configuration-and-vhost-setup.md when broker credentials or vhost setup are the blocker. Open references/delayed-exchange-and-broker-events.md when delayed delivery semantics or broker-side events are the blocker.
Use one converter strategy per module unless interoperability requirements force otherwise.
@Bean
JacksonJsonMessageConverter jsonConverter() {
return new JacksonJsonMessageConverter();
}
The ordinary path is one JSON payload type per message contract, with the listener receiving the already-converted domain payload. Open references/conversion-and-listener-method-signatures.md when the blocker is listener argument design, header access, validation, or custom conversion behavior.
Use RabbitTemplate for send and receive paths, and @RabbitListener for the ordinary consumer path.
@Service
class OrderPublisher {
private final RabbitTemplate rabbitTemplate;
OrderPublisher(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
void publish(OrderCreated event) {
rabbitTemplate.convertAndSend("orders.exchange", "orders.created", event);
}
}
@Component
class OrderListener {
private final OrderService orderService;
OrderListener(OrderService orderService) {
this.orderService = orderService;
}
@RabbitListener(queues = "orders")
void handle(OrderCreated event) {
orderService.process(event);
}
}
RabbitTemplate receive operations only when the consumer contract is actually synchronous.Open references/polling-receive.md when the caller needs scheduled or command-driven pull semantics.
Open references/request-reply.md when the caller truly needs synchronous broker-mediated reply semantics.
Open references/publisher-confirms-returns-and-send-reliability.md when the producer must detect unroutable messages, broker acceptance, or other send-side delivery uncertainty.
Use confirms and returns only when the producer contract must distinguish broker acceptance from publish attempt and unroutable delivery.
spring:
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true
template:
mandatory: true
@Bean
RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setConfirmCallback((correlationData, ack, cause) -> {
});
template.setReturnsCallback(returned -> {
});
return template;
}
Keep request-reply timeout explicit whenever the caller truly needs synchronous broker-mediated reply semantics.
rabbitTemplate.setReplyTimeout(5000);
Open references/request-reply.md when the producer-consumer contract is genuinely request-reply rather than an event flow.
Start with one baseline container factory and keep advanced concurrency or prefetch tuning out of the common path.
@Bean
SimpleRabbitListenerContainerFactory ordersListenerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
Use a dedicated factory only when a listener truly needs different acknowledgment, retry, or concurrency rules. Open references/container-variants-and-concurrency.md when default listener-container behavior is not enough and the blocker is container choice, prefetch, concurrency, or ordering tradeoffs.
Wire the first production signals before tuning concurrency or retry behavior.
Open references/listener-metrics-and-micrometer.md when the blocker is Micrometer metrics. Open references/distributed-tracing-for-amqp.md when publish and consume traces must correlate. Open references/delivery-debugging-checklist.md when delivery diagnosis is the blocker.
Choose one retry policy per consumer path and make the exhausted-message outcome explicit.
RetryOperationsInterceptor interceptor = RetryInterceptorBuilder.stateless()
.maxAttempts(3)
.recoverer(new RejectAndDontRequeueRecoverer())
.build();
For the common path:
Open references/retry-recovery-and-transactions.md when the blocker is transactional retry, recoverer choice, or deeper failure classification.
Verify the first Spring AMQP path with one delivery test and one failure-path test.
@SpringRabbitTest
class OrderMessagingTests {
}
Open references/testing-support-and-listener-harnesses.md when the task needs listener-test harnesses, broker-backed integration depth, or repeatable contract checks.
orders
orders.exchange
orders.created
orders.dlq
rabbitTemplate.convertAndSend("orders.exchange", "orders.created", event);
@RabbitListener(queues = "orders")
void handle(OrderCreated event) {
orderService.process(event);
}
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
Return: