Search code examples
spring-integrationspring-amqpspring-rabbit

Redeclaration of a binding after queue has been recovered


I'm currently working on a rabbit-amqp implementation project and use spring-rabbit to programmatically setup all my queues, bindings and exchanges.

I'm trying to recreate an queue if it was deleted and found the following in the reference documentation :

3.14 Listener Container Queues

Version 1.3 introduced a number of improvements for handling multiple queues in a listener container.

The container must be configured to listen on at least one queue; this was the case previously too, but now queues can be added and removed at runtime. The container will recycle (cancel and re-create) the consumers when any pre-fetched messages have been processed. See methods addQueues, addQueueNames, removeQueues and removeQueueNames. When removing queues, at least one queue must remain.

A consumer will now start if any of its queues are available - previously the container would stop if any queues were unavailable. Now, this is only the case if none of the queues are available. If not all queues are available, the container will attempt to passively declare (and consume from) the missing queue(s) every 60 seconds. ... (source: http://docs.spring.io/spring-amqp/docs/1.3.4.RELEASE/reference/html was down during the time of writing)

I tried this scenario and indeed my queues are recreated, but the bindings between the queues and exchanges are lost. How can I recreate my queues with their bindings after they have been deleted?


Solution

  • Actually it should work, if all your declarations (Queue, Exchange, Binding) are registered as beans.

    On each queuesChanged() SimpleMessageListenerContainer invokes rabbitAdmin.initialize(), who, in turn, gets deal with mentioned RabbitMQ environment.

    It happens only in this case:

    if (queueNames.contains(queue.getName()) && queue.isAutoDelete()
                            && this.rabbitAdmin.getQueueProperties(queue.getName()) == null) {
    

    If the Queue from application context contains in the current queueNames, it is auto-delete and it doesn't exist on Broker (rabbitAdmin.getQueueProperties) tries to connect to Broker to get info about Queue.

    UPDATE

    Right, of course, the queue is deleted, when there is no consumer.

    Looks like you are right regarding x-expires(Queue TTL) and we should get deal with that, too:

    if (queueNames.contains(queue.getName())
              && (queue.isAutoDelete() || queue.getArguments().containsKey("x-expires")))
          && this.rabbitAdmin.getQueueProperties(queue.getName()) == null) {
    

    Feel free to raise a JIRA issue: https://jira.spring.io/browse/AMQP

    Thank you for pointing it out - +1