Spring AMQP - Sender and Receiving Messages
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Spring AMQP is the Spring abstraction most commonly used with RabbitMQ to send and receive messages without writing low-level client code everywhere. A basic setup needs three things: broker infrastructure, a sender, and a listener. The harder part is not sending the first message. It is deciding how messages are routed, serialized, retried, and handled when consumers fail.
Define Queue, Exchange, and Binding Clearly
A lot of examples send directly to a queue, but explicit exchanges and bindings scale better because routing stays visible.
This keeps queue names and routing keys explicit and avoids hidden broker assumptions.
Send Messages with RabbitTemplate
For sending, Spring AMQP uses RabbitTemplate.
convertAndSend is convenient because it works with Spring’s message converters rather than forcing you to serialize manually in every sender.
Prefer JSON Payloads Over Java Serialization
For most service-to-service messaging, JSON is easier to inspect and safer to integrate than default Java serialization.
With that in place, a compact payload type works well.
That keeps the on-the-wire message readable and makes cross-service integration much easier.
Receive Messages with @RabbitListener
The consumer side is usually implemented with @RabbitListener.
Spring creates the listener container, subscribes to the queue, and invokes your method when a message arrives.
Think About Failure Handling Early
Messaging design becomes serious when processing can fail. A consumer that crashes after updating one table but before finishing all side effects may see the same message again. That means message handlers should generally be idempotent or at least duplicate-safe.
You should also decide what happens after repeated failures. A message should not usually loop forever with no observability. Dead-letter queues, retry policies, and alerting are part of the design, not optional cleanup.
The sender and receiver code may look simple, but the production behavior is defined by these operational choices.
Keep Business Logic Out of Messaging Glue
A healthy Spring AMQP design keeps infrastructure in configuration classes, publishing in sender services, and business logic in application services called by listeners. If the listener method grows into a large transaction script, the messaging layer becomes hard to test and harder to reason about.
The listener should usually validate the message shape, call a service, and let that service own the business workflow.
Common Pitfalls
- Sending directly to queues everywhere and never defining exchanges or routing explicitly.
- Using Java object serialization when a JSON payload would be easier to inspect and integrate.
- Putting too much domain logic directly inside listener methods.
- Ignoring idempotency and assuming messages are processed exactly once.
- Leaving failures in endless redelivery loops without a retry or dead-letter strategy.
Summary
- Spring AMQP typically uses queues, exchanges, and bindings plus a sender and listener.
- '
RabbitTemplatepublishes messages, and@RabbitListenerconsumes them.' - JSON conversion is usually a better default than Java serialization.
- Reliable messaging requires thought about retries, duplicates, and dead-letter behavior.
- Keep the messaging layer thin and let application services own the business work.
Related reading
- Spring AMQP + RabbitMQ 3.3.5 ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN
- Spring AMQP (Rabbit) Listener goes in a loop in case of exception
- Spring AMQP RabbitMQ implementing priority queue
- Spring Apache Kafka onFailure Callback of KafkaTemplate not fired on connection error
- Spring amqp converter issue using rabbit listener
- Spring boot on Kubernetes does not get restarted on java.lang.OutOfMemoryError Java heap space
- Spring and scheduled tasks on multiple instances
- Spring AOP vs AspectJ

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.