Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Queues on RabbitListener Annotation

I'd like to use queue names using a specific pattern, like project.{queue-name}.queue. And to keep this pattern solid, I wrote a helper class to generate this name from a simple identifier. So, foo would generate a queue called project.foo.queue. Simple.

But, the annotation RabbitListener demands a constant string and gives me an error using my helper class. How can I achieve this (or maybe another approach) using RabbitListener annotation?

@Component
public class FooListener {

    // it doesn't work
    @RabbitListener(queues = QueueName.for("foo"))
    // it works
    @RabbitListener(queues = "project.foo.queue")
    void receive(final FooMessage message) {
       // ...
    }
}
like image 298
robsonrosa Avatar asked Apr 18 '18 22:04

robsonrosa


2 Answers

To create and listen to a queue name constructed from a dynamic UUID, you could use random.uuid.

The problem is that this must be captured to a Java variable in only one place because a new random value would be generated each time the property is referenced.

The solution is to use Spring Expression Language (SpEL) to call a function that provides the configured value, something like:

@RabbitListener(queues = "#{configureAMQP.getControlQueueName()}")
void receive(final FooMessage message) {
       // ...
}

Create the queue with something like this:

@Configuration
public class ConfigureAMQP {

    @Value("${controlQueuePrefix}-${random.uuid}")
    private String controlQueueName;

    public String getControlQueueName() {
        return controlQueueName;
    }

    @Bean
    public Queue controlQueue() {
        System.out.println("controlQueue(): controlQueueName=" + controlQueueName);
        return new Queue(controlQueueName, true, true, true);
    }

}

Notice that the necessary bean used in the SpEL was created implicitly based on the @Configuration class (with a slight alteration of the spelling ConfigureAMQP -> configureAMQP).

like image 161
s7vr Avatar answered Nov 02 '22 02:11

s7vr


Declare a magic bean, in this case implicitly named queueName:

@Component
public class QueueName {
    public String buildFor(String name) {
        return "project."+name+".queue";
    }
}

Access this using a "constant string" that will be evaluated at runtime:

@RabbitListener(queues = "#{queueName.buildFor(\"foo\")}")
like image 9
Brent Bradburn Avatar answered Nov 02 '22 04:11

Brent Bradburn