I created two queue configurations each having its own @RabbitListener
annotated methods.
@Configuration
@EnableRabbit
public class TestQueue extends QueueConfiguration {
public String getQueueName() {
return "testQueue";
}
public String getRoutingKey() {
return "testKey";
}
@RabbitListener(queues = "testQueue")
public void receive(Message message) { ... }
}
Another queue configuration
@Configuration
@EnableRabbit
public class AnotherTestQueue extends QueueConfiguration {
public String getQueueName() {
return "anotherTestQueue";
}
public String getRoutingKey() {
return "anotherTestKey";
}
@RabbitListener(queues = "anotherTestQueue")
public void receive(Message message) { ... }
}
Here is the base queue configuration where I create queue, exchange and binding:
public abstract class QueueConfiguration {
@Bean
public Queue mainQueue() {
return new Queue(getQueueName());
}
@Bean
public DirectExchange mainExchange() {
return new DirectExchange("main.exchange");
}
@Bean
public Binding mainExchangeBinding() {
return BindingBuilder.build(mainQueue()).to(mainExchange()).with(getRoutingKey());
}
// getQueueName() and getRoutingKey() are abstract methods
}
Now the common configuration class
@Configuration
public class CommonConfiguration {
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,
WfmMessageListener listener) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
factory.setAdviceChain(listener);
return factory;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
}
When I start the app, I get the following error:
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method(reply-code=404, reply-text=NOT_FOUND - no queue 'testQueue' in vhost '/', class-id=50, method-id=10) at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:505) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:336) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:143) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:90) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.AMQConnection.readFrame(AMQConnection.java:634) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.AMQConnection.access$300(AMQConnection.java:47) ~[amqp-client-4.0.3.jar:4.0.3] at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:572) ~[amqp-client-4.0.3.jar:4.0.3]
I tried with just one queue configuration, it works fine! When I have more than one rabbit listener, it is throwing this error. Kindly help.
public abstract class QueueConfiguration
The Queue
definition @Bean
s have to have unique bean names (the bean name is the method name, by default); since your config classes both subclass QueueConfiguration
you will end up with one @Bean
called mainQueue
. The first definition is overridden by the second.
You need to move that @Bean
into the subclasses and give them unique bean names
public abstract Queue mainQueue();
@Override
@Bean("someBeanName")
public Queue mainQueue() {
return new Queue(getQueueName());
}
@Override
@Bean("someOtherBeanName")
public Queue mainQueue() {
return new Queue(getQueueName());
}