Implementing Messaging with RabbitMQ

1. Adding RabbitMQ Dependencies

Example: RabbitMQ AMQP dependency

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2. Configuring RabbitMQ Connection Properties

Property Default
spring.rabbitmq.host localhost
spring.rabbitmq.port 5672
spring.rabbitmq.username guest
spring.rabbitmq.password guest
spring.rabbitmq.virtual-host /
spring.rabbitmq.ssl.enabled false
spring.rabbitmq.publisher-confirm-type correlated

3. Creating RabbitTemplate for Sending Messages

Example: Publish message with RabbitTemplate

@Service
public class OrderPublisher {
  private final RabbitTemplate rabbit;
  public OrderPublisher(RabbitTemplate rabbit) { this.rabbit = rabbit; }
  public void publish(OrderPlaced evt) {
    rabbit.convertAndSend("orders.exchange", "order.placed", evt);
  }
}

4. Defining Queues, Exchanges, and Bindings

Example: Declare queue, exchange, and binding

@Configuration
public class RabbitConfig {
  @Bean Queue ordersQueue() { return QueueBuilder.durable("orders.q").build(); }
  @Bean TopicExchange ordersExchange() { return new TopicExchange("orders.exchange"); }
  @Bean Binding bind(Queue q, TopicExchange ex) {
    return BindingBuilder.bind(q).to(ex).with("order.*");
  }
}
Exchange Type Routing
direct Exact key match
topic Wildcards (* and #)
fanout Broadcast to all bindings
headers Header attribute match

5. Sending Messages to Queues (convertAndSend)

Example: Send message with headers and TTL

rabbit.convertAndSend("exchange", "routing.key", payload, msg -> {
  msg.getMessageProperties().setHeader("X-Source", "orders-svc");
  msg.getMessageProperties().setExpiration("60000");
  return msg;
});

6. Creating Message Listeners (@RabbitListener)

Example: Consume messages with concurrency

@Component
public class OrderConsumer {
  @RabbitListener(queues = "orders.q", concurrency = "4-10")
  public void handle(OrderPlaced evt, @Header("X-Source") String source) {
    /* process */
  }
}

7. Configuring Message Converters (Jackson2JsonMessageConverter)

Example: Configure JSON message converter

@Bean MessageConverter jsonConverter() { return new Jackson2JsonMessageConverter(); }
@Bean RabbitTemplate rabbitTemplate(ConnectionFactory cf, MessageConverter mc) {
  RabbitTemplate t = new RabbitTemplate(cf);
  t.setMessageConverter(mc);
  return t;
}

8. Handling Message Acknowledgments

Mode Behavior
NONE Auto-ack on delivery (no redelivery)
AUTO (default) Ack after listener returns; nack on exception
MANUAL Listener calls channel.basicAck()

Example: Manual acknowledgement mode

spring.rabbitmq.listener.simple.acknowledge-mode: manual

9. Implementing Dead Letter Queues

Example: Dead letter queue configuration

@Bean Queue ordersQ() {
  return QueueBuilder.durable("orders.q")
    .withArgument("x-dead-letter-exchange", "orders.dlx")
    .withArgument("x-dead-letter-routing-key", "orders.dead")
    .withArgument("x-message-ttl", 30_000)
    .build();
}
@Bean Queue dlq() { return QueueBuilder.durable("orders.dlq").build(); }
@Bean DirectExchange dlx() { return new DirectExchange("orders.dlx"); }
@Bean Binding dlBind() { return BindingBuilder.bind(dlq()).to(dlx()).with("orders.dead"); }

10. Using Message Properties and Headers

Property Use
messageId Unique id for dedup
correlationId Request/response correlation
contentType Auto-set by converter
expiration TTL (ms, string)
priority 0–9 (queue must support)
headers Custom map

11. Configuring Retry and Error Handling

Example: Retry with exponential backoff

spring:
  rabbitmq:
    listener:
      simple:
        retry:
          enabled: true
          initial-interval: 1s
          max-attempts: 5
          multiplier: 2
          max-interval: 30s

12. Using Publisher Confirms and Returns

Example: Publisher confirm and return callbacks

rabbit.setMandatory(true);
rabbit.setConfirmCallback((corr, ack, cause) -> {
  if (!ack) log.error("Publish failed: {}", cause);
});
rabbit.setReturnsCallback(ret -> log.warn("Returned: {}", ret));