Messages lost if queue does not exist

Viewed 5488

When we send the messages to RabbitMQ and if queue doesn't exist, messages are lost without throwing any error.

Where the messages will be posted to? Dead queue?

2 Answers

Your messages can be returned back to you

If there are no queues bound to an exchange. To receive them back and not to lose these messages, you must do the following:

1. Add these properties to your application.yml

spring:
  rabbitmq:
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true

2. Create RabbitConfirmCallback

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

@Component
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback {
    private static final Logger logger = LoggerFactory.getLogger(RabbitConfirmCallback.class);

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack && correlationData != null && correlationData.getId() != null) {

            Message returnedMessage = correlationData.getReturnedMessage();
            String dataId = correlationData.getId();

            if (returnedMessage != null) {
                logger.error("Message wasn't delivered to Consumer; " + returnedMessage + "\nCorrelationData id = " + dataId);
            } else {
                logger.info("CorrelationData with id " + dataId + " acknowledged;");
            }

        } else {
            if (ack) {
                logger.warn("Unknown message acknowledgement received: " + correlationData);
            } else {
                logger.info("Broker didn't accept message: " + cause);
            }
        }
    }
}

This callback method confirm(...) will be triggered, right after trial of sending message in such an exchange without bounded queues. In correlationData object, you will find returnedMessage field where will be messageProperties and body of your message

3. Set RabbitConfirmCallback to RabbitTemplate

@Autowired
public void post(RabbitTemplate rabbitTemplate, RabbitConfirmCallback rabbitConfirmCallback){
    rabbitTemplate.setConfirmCallback(rabbitConfirmCallback);
}

4. When you are sending your messages, add CorrelationDate object

With some unique identifier

rabbitTemplate.convertAndSend(exchange, routingKey, wrapMessage(message),
                              new CorrelationData(stringId));
Related