Search code examples
spring-rabbit

How to dynamically create bindings using "Declarables" in RabbitMQ Spring Framework


My code gets user's input which is a list of routing keys and use them to bind a queue with an exchange. I use Declarables to generate the bindings for each routing key. The problem is, the number of routing keys that the user inputs varies each time. Considering the list of routing keys are on an array, how to bind a queue to the exchange with those routing keys. Below is my current code.

@Bean
public Declarables bindings() {
    return new Declarables(
            BindingBuilder.bind(queue()).to(exchange()).with(routingKey[0]),
            BindingBuilder.bind(queue()).to(exchange()).with(routingKey[1]),
            BindingBuilder.bind(queue()).to(exchange()).with(routingKey[2])
    );
}

EDIT - adding exact use case for more clarity:

I'm using rabbitmq event exchange plugin to consume internal events(https://www.rabbitmq.com/event-exchange.html). I'm creating a queue and binding it with an exchange(amq.rabbitmq.event) that is created by the plugin. Different types of events can be consumed by binding respective routing keys.

I get the list of routing keys from the user each time and bind it to the exchange amq.rabbitmq.event and consume respective events(e.g. queue.created, user.authentication.success, etc). User adds all the routing keys as a comma separated value in application.properties file. I parse it and add these values to an array and create bindings for all the elements(routing keys) in this array. The size of this list is not constant. User may input 3 routing keys or 5 or a different number of keys each time and I have to create a binding for each of the routing key.

In the code above, bindings are created for 3 routing keys(routingKey[0], routingKey[1] & routingKey[2]). What if user inputs more than 3 routing keys and how to create bindings for all of them.


Solution

  • the number of routing keys that the user inputs varies each time.

    It's not clear from your description whether you need a variable number of routing keys statically or dynamically.

    You can use RabbitAdmin.declareBinding(...) to declare bindings at runtime (dynamically).

    However, this should NOT be used within a @Bean definition.

    EDIT

    Based on your updated description; Spring will automatically convert a comma-delimited list to a List.

    routing.keys=foo,bar,baz
    
    @Bean
    public Declarables bindings(@Value("${routing.keys}") List<String> keys) {
        return new Declarables(keys.stream()
                .map(key -> BindingBuilder.bind(queue()).to(exchange()).with(key))
                .collect(Collectors.toList()));
    }