1
votes

I have configured my rabbit properties via application.yaml and spring configurationProperties. Thus, when I configure exchanges, queues and bindings, I can use the getters of my properties

@Bean Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(properties.getQueue());
}

@Bean Queue queue() {
    return new Queue(properties.getQueue(), true);
}

@Bean TopicExchange exchange() {
    return new TopicExchange(properties.getExchange());
}

However, when I configure a @RabbitListener to log the messages on from the queue, I have to use the full properties name like

 @RabbitListener(queues = "${some.long.path.to.the.queue.name}") 
 public void onMessage(
            final Message message, final Channel channel) throws Exception {
       log.info("receiving message: {}#{}", message, channel);
    }

I want to avoid this error prone hard coded String and refer to the configurationProperties bean like:

@RabbitListener(queues = "${properties.getQueue()}") 

I had a similar issue once with @EventListener where using a bean reference "@bean.method()" helped, but it does not work here, the bean expression is just interpreted as queue name, which fails because a queue namde "@bean...." does not exist.

Is it possible to use ConfigurationProperty-Beans for RabbitListener queue configuration?

4
The spring doc says: "If the evaluation context has been configured with a bean resolver it is possible to lookup beans from an expression using the (@) symbol." So I guess thats not the case for Rabbit ... - Jan Galinski

4 Answers

4
votes

Something like this worked for me where I just used the Bean and SpEL.

@Autowired
Queue queue;

@RabbitListener(queues = "#{queue.getName()}")
1
votes

I was finally able to accomplish what we both desired to do by taking what @David Diehl suggested, using the bean and SpEL; however, using MyRabbitProperties itself instead. I removed the @EnableConfigurationProperties(MyRabbitProperties.class) in the config class, and registered the bean the standard way:

@Configuration
//@EnableConfigurationProperties(RabbitProperties.class)
@EnableRabbit
public class RabbitConfig {
  //private final MyRabbitProperties myRabbitProperties;

  //@Autowired
  //public RabbitConfig(MyRabbitProperties myRabbitProperties) {
    //this.myRabbitProperties = myRabbitProperties;
  //}      

  @Bean 
  public TopicExchange myExchange(MyRabbitProperties myRabbitProperties) {
    return new TopicExchange(myRabbitProperties.getExchange());
  }

  @Bean
  public Queue myQueueBean(MyRabbitProperties myRabbitProperties) {
    return new Queue(myRabbitProperties.getQueue(), true);
  }

  @Bean 
  public Binding binding(Queue myQueueBean, TopicExchange myExchange, MyRabbitProperties myRabbitProperties) {
    return BindingBuilder.bind(myQueueBean).to(myExchange).with(myRabbitProperties.getRoutingKey());
  }

  @Bean
  public MyRabbitProperties myRabbitProperties() {
    return new MyRabbitProperties();
  }
}

From there, you can access the get method for that field:

@Component
public class RabbitQueueListenerClass {

  @RabbitListener(queues = "#{myRabbitProperties.getQueue()}") 
  public void processMessage(Message message) {

  }
}
0
votes
@RabbitListener(queues = "#{myQueue.name}") 
0
votes

Listener:

@RabbitListener(queues = "${queueName}")

application.properties:

queueName=myQueue