Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring with AMQP and RabbitMQ, queue with optional x-dead-letter-exchange

I have an existing queue created in RabbitMQ. It can be created with or without x-dead-letter-exchange parameter. I am creating a consumer of this queue in Spring using the RabbitTemplate. When I declare the queue, I don't want to specify the x-dead-letter-exchange parameter. I would like the template to somehow figure it itself or not care. I am throwing AmqpRejectAndDontRequeueException from my consumer to indicate bad messages, but I want the creator of the queue to be responsible for the decision whether or not to create an exchange and queue for the rejected messages.

Here is my bean that declares the queue in Spring:

@Bean
Queue queue() {
    Map<String, Object> args = new HashMap<>();
    // set the queue with a dead letter feature
    args.put("x-dead-letter-exchange", REJECTED_EXCHANGE);
    args.put("x-dead-letter-routing-key", REJECTED_ROUTING_KEY);
    Queue queue = new Queue(Constants.QUEUE_NAME, false, false, false, args);
    return queue;
}

This works fine, but when the creator of the queue decides not to use the dead letter feature, I see the following error:

Channel shutdown: channel error; protocol method: #method<channel.close>
(reply-code=406, reply-text=PRECONDITION_FAILED - 
inequivalent arg 'x-dead-letter-exchange' for queue 'queueName'

The message is a bit longer, it continues telling me which side has which x-dead-letter-exchange (none or a name of the exchange). I've tried different combinations (e.g. creating the queue with exchange and not specifying it in the Spring or creating the queue without the exchange and specifying it in the Spring), only to see different variants of this message.

How do I declare the queue so it simply accepts whatever parameters are already set in the queue?

like image 982
MartinTeeVarga Avatar asked Aug 11 '15 09:08

MartinTeeVarga


People also ask

How do I set dead letter exchange in RabbitMQ?

To set the dead letter exchange for a queue, specify the optional x-dead-letter-exchange argument when declaring the queue. The value must be an exchange name in the same virtual host: channel. exchangeDeclare("some.exchange.name", "direct"); Map<String, Object> args = new HashMap<String, Object>(); args.

What is the difference between exchange and queue in RabbitMQ?

In RabbitMQ, a producer never sends a message directly to a queue. Instead, it uses an exchange as a routing mediator. Therefore, the exchange decides if the message goes to one queue, to multiple queues, or is simply discarded.

What is dead-letter queue in RabbitMQ?

Dead-letter exchanges in Message Queue for RabbitMQ are used to process the messages that are negatively acknowledged by consumers or for which all retries fail.

How do I read messages from dead-letter queue RabbitMQ?

You need to configure a "dead letter queue" to handle messages that have been rejected or undelivered. Using the RabbitMQ Client library, you can bind a consumer to that configured queue and retrieve the messages from it. From there you decide in code what you want to do to reprocess/reject them completely.


2 Answers

As you can see in the spring docs: The RabbitMQ broker will not allow declaration of a queue with mismatched arguments., so you can't do it.
In the RabbitMQ Java API there is a method to check whether a queue already exists: queueDeclarePassive.

If the Spring AMQP API provides a similar functionality you can use it before trying to declare the queue.

like image 180
Toresan Avatar answered Sep 29 '22 11:09

Toresan


Yes, The possible cause is - if you declare some queues manually and later your program (client in code) tries to create one (based on the settings you had in code) then you get this error. The reason behind it is when your code (client application) tries to access one queue. It gets a signal from the server that the connection is not available for this.

To solve this problem

  • Delete all the queues that you have created manually, and let the client program create them by itself.
  • If you got problems in deleting the queues, because of some data is there in it, or for some reason, you want to maintain it, create one queue manually, and move all the queue data to be deleted in it through "Move" tab of the queue.
like image 32
Ajay Sodhi Avatar answered Sep 29 '22 12:09

Ajay Sodhi