2

I have a Spring Boot application that spins consumers for a section of queues and I want to be able to add queues to those consumers at run time.

I've installed the event exchange plugin (https://www.rabbitmq.com/event-exchange.html) and I created a dedicated queue that is bound to the amq.rabbitmq.event exchange. I can see the events coming in when I declare the queues statically.

How would I accomplish this run time magic? I've seen people use the property file, but I would prefer not to have to modify the property file during run time as I add more queues

@Component
public class MessageConsumer {

    List<String> allQueues = new ArrayList<String>();

    public MessageConsumer() {
        allQueues.add("queue1");
        allQueues.add("queue2");
        allQueues.add("queue3");
    }

    @RabbitListener(id = "event", queues = {"custom-emp-queue-events"}) // create this queue in rabbitmq management, bound to amqp exchange
    public void processQueueEvents(Message message) {
        ... add the queue to the allQueues list on queue.created ...
    }

    @RabbitListener(id = "process", queues = allQueues.stream().toArray(String[]::new) ) // this is where the "issue" is
    public void processMessageFromQueues(String messageAsJson) {
        ... process message ...
    }
}
user10776719
  • 301
  • 4
  • 15

1 Answers1

4

This can be done with a SpEL expression over there:

@RabbitListener(id = "process", queues = "#{messageConsumer.allQueues}" )

But you have to add a public getter for that allQueues.

See more info in the Reference Manual: https://docs.spring.io/spring-amqp/docs/2.1.3.RELEASE/reference/html/_reference.html#async-annotation-driven

UPDATE

@Autowired
private RabbitListenerEndpointRegistry listenerEdnpointRegistry;

@RabbitListener(id = "event", queues = {"custom-emp-queue-events"}) // create this queue in rabbitmq management, bound to amqp exchange
public void processQueueEvents(Message message) {
    ((AbstractMessageListenerContainer) this.listenerEdnpointRegistry.getListenerContainer("process")).addQueueNames(...);
}
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • 1
    But that is still statically processed, once; to add queues at runtime, you need to use the technique I described in [this answer to your earlier question](https://stackoverflow.com/questions/54094994/dynamic-addition-of-queues-to-a-rabbit-listener-at-runtime/54096620#54096620). – Gary Russell Jan 14 '19 at 18:36
  • @GaryRussell - Will look at this again, I thought this was the way around it and I was wrong. I had some issues trying to determine exactly when/how I would retrieve the container "process" listed in my code. I added an autowired RabbitListenerEndpointRegistry property to this class originally, – user10776719 Jan 14 '19 at 19:16
  • 2
    See an UPDATE in my answer. – Artem Bilan Jan 14 '19 at 19:19
  • Ah - OK, now it makes sense what Gary was saying. Thank you to both of you! – user10776719 Jan 14 '19 at 19:27