Home/Learn/RabbitMQ/RabbitTemplate

RabbitTemplate

Intermediate
Spring AMQP

RabbitTemplate provides convertAndSend, convertSendAndReceive (synchronous RPC), and receive/receiveAndConvert for flexible produce/consume operations.

Overview

RabbitTemplate is the central Spring AMQP class for interacting with RabbitMQ from producer code. It provides: convertAndSend (fire-and-forget), convertSendAndReceive (synchronous RPC — send and block for a reply), send (raw Message), and receive/receiveAndConvert (polling consumer). It handles connection management, serialisation/deserialisation via MessageConverter (default: SimpleMessageConverter for byte arrays / JSON via Jackson2JsonMessageConverter), and correlation ID generation for RPC patterns. RabbitTemplate is thread-safe and should be used as a singleton bean.

convertAndSend — fire-and-forget publishing

convertAndSend serialises the message payload using the configured MessageConverter (default SimpleMessageConverter, or Jackson2JsonMessageConverter for JSON) and publishes to the specified exchange with the routing key. The MessagePostProcessor variant allows setting message properties (headers, expiration, priority) before sending.

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;
        });
    }
}

convertSendAndReceive — synchronous RPC over RabbitMQ

convertSendAndReceive implements the request-reply pattern: it publishes a message with a reply-to header pointing to a temporary auto-delete queue, then blocks waiting for a reply on that queue. The server processes the request and publishes the response with the matching correlation ID. This pattern synchronises over async messaging — useful for internal service calls where async processing is overkill.

Java — synchronous RPC with convertSendAndReceive and async variant
// RPC pattern: request-reply over RabbitMQ
// Caller (blocking)
@Service
public class PricingClient {

    private final RabbitTemplate rabbitTemplate;

    public PriceResponse getPrice(PriceRequest request) {
        // Sends to "pricing" exchange, blocks until reply arrives
        // Returns null if no reply within replyTimeout (default 5s)
        PriceResponse response = (PriceResponse) rabbitTemplate
            .convertSendAndReceive("pricing", "price.calculate", request);

        if (response == null) {
            throw new PricingServiceTimeoutException("Pricing timeout");
        }
        return response;
    }
}

// Server (responder) — @RabbitListener handles request and replies
@Service
public class PricingService {

    @RabbitListener(queues = "pricing.calculate.queue")
    public PriceResponse calculatePrice(PriceRequest request) {
        // Return value is automatically sent back to the reply-to queue
        BigDecimal price = calculateBasePrice(request.getProductId())
            .multiply(request.getQuantity());
        return new PriceResponse(price, "USD");
    }
}

// Configure reply timeout
template.setReplyTimeout(10_000);   // 10 seconds (default 5s)

// For async RPC: use AsyncRabbitTemplate instead of blocking
AsyncRabbitTemplate asyncTemplate = new AsyncRabbitTemplate(rabbitTemplate);
CompletableFuture<PriceResponse> future =
    asyncTemplate.convertSendAndReceive("pricing", "price.calculate", request);

Publisher confirms and mandatory messages

Publisher confirms (RabbitMQ publisher confirms / confirms callback) verify that the broker has accepted the message. Mandatory flag returns unroutable messages via a return callback. Use both for mission-critical messages where you need assurance that the broker received and routed the message.

Java — publisher confirms and mandatory returns for reliable publishing
// Publisher confirms — verify broker accepted message
@Bean
public RabbitTemplate confirmingRabbitTemplate(CachingConnectionFactory factory) {
    factory.setPublisherConfirmType(
        CachingConnectionFactory.ConfirmType.CORRELATED);
    factory.setPublisherReturns(true);

    RabbitTemplate template = new RabbitTemplate(factory);
    template.setMessageConverter(new Jackson2JsonMessageConverter());
    template.setMandatory(true);   // return unroutable messages

    // Confirm callback — called when broker acks/nacks the message
    template.setConfirmCallback((correlationData, ack, cause) -> {
        if (!ack) {
            log.error("Message nacked by broker: {}", cause);
            // retry or alert
        }
    });

    // Return callback — called when message cannot be routed
    template.setReturnsCallback(returned -> {
        log.error("Message returned — unroutable: exchange={} routingKey={}",
            returned.getExchange(), returned.getRoutingKey());
    });

    return template;
}

// Send with correlation data for tracking
CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("payments", "payment.initiated", event, cd);

Key Points to Remember

  • 1Use Jackson2JsonMessageConverter bean to enable JSON serialisation — default SimpleMessageConverter uses Java serialisation
  • 2convertAndSend is fire-and-forget; convertSendAndReceive blocks until a reply arrives (synchronous RPC over AMQP)
  • 3MessagePostProcessor lambda in convertAndSend allows setting headers, TTL, priority, and correlation ID per message
  • 4Publisher confirms verify broker acceptance; mandatory flag returns unroutable messages via callback
  • 5RabbitTemplate is thread-safe — use as a singleton; do not create per-request instances
  • 6For async RPC, use AsyncRabbitTemplate which returns CompletableFuture instead of blocking

Interview Questions

Sign in to ask Aria
1

What is the difference between convertAndSend and convertSendAndReceive in RabbitTemplate?

EasyInfosys
2

How does the RPC pattern work over RabbitMQ — what headers are involved?

MediumThoughtworks
3

What are publisher confirms and when would you use them?

MediumAmazon
4

Why is Jackson2JsonMessageConverter important and what does the default converter use instead?

EasyWipro
5

What does the mandatory flag do in RabbitTemplate and what is the return callback?

HardNetflix

Ask Aria about RabbitTemplate

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.

Loading discussion…