I want to run some acceptance tests for my services that are using rabbitMq but I want to ignore all that require inter-service communication (amqp).
The problem however is that Spring tries to connect to the (non-exisiting) rabbit host on startup so it can register its consumers. It does that for each method that is annotated with @RabbitListener
which can get quite annoying with the long timeout this has if I have more than one listener in my service.
How can I reduce this timeout or even prevent @RabbitListener connection all together?
Our (simplified) Rabbit Config:
@Configuration
@EnableRabbit
public class RabbitMqConfig {
public RabbitMqConfig(
@Value("${rabbitmq.host}") String rabbitHost,
@Value("${rabbitmq.port}") int rabbitPort,
@Value("${exchange.name}") String exchange) {
this.rabbitHost = rabbitHost;
this.rabbitPort = rabbitPort;
this.exchange= exchange;
}
@Bean
DirectExchange directExchangeBean() {
return new DirectExchange(this.exchange, true, false);
}
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitHost);
connectionFactory.setPort(rabbitPort);
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
@Bean
public Queue itemDoneQueue() {
return new Queue(ITEM_DONE_QUEUENAME, true);
}
@Bean
Binding itemDoneBinding() {
return BindingBuilder.bind(itemDoneQueue()).to(directExchangeBean()).with(ITEM_DONE_KEY);
}
}
Properties
rabbitmq.host=192.168.42.100
rabbitmq.port=5672
exchange.name=myExchange
The Listener:
@RabbitListener(queues = ITEM_DONE_QUEUENAME)
public void receiveMessageFromItemDoneQueue(String message) {
// do the work
}
The Test:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public abstract class RabbitTest {
Really nothing special here. Obviously during testing the rabbit host is unavailable. That is fine. I want to ignore the fact. And quickly.
I've tried
spring.rabbitmq.connection-timeout=1
But that didn't change anything.
Using
spring.rabbitmq.listener.simple.auto-startup=false
neither does anything.
Using
spring.autoconfigure.exclude:org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
just kills my application context loading with spring complaining about a NoSuchBeanDefinitionException: No bean named 'rabbitListenerContainerFactory' available
Any ideas? Thanks!
I would expect the spring.rabbitmq.listener.simple.auto-startup=false
to work - are you sure you're not trying to connect to Rabbit with some other code? Can you provide a DEBUG log to show the problem when that is set to false?
You can use the JUnit BrokerRunning
@Rule to skip any tests that need a real RabbitMQ broker.
I've had a similar problem, but solved it with
spring.rabbitmq.listener.direct.auto-startup=false
SpringBoot version 2.2.4.RELEASE
Spring framework version 5.2.3.RELEASE
Instead of
spring.rabbitmq.listener.simple.auto-startup=false
I have used the below (with out the word 'simple' in the prop name) and it did work for me
spring.rabbitmq.listener.auto-startup=false
Thanks for your input Gary.
I already found a solution that works for me. For some reason the connection timeout for the Consumer initialization is not exposed in the CachingConnectionFactory
I used nor is the property used that I tried (spring.rabbitmq.connection-timeout
).
What I do now is initialize the base ConnectionFactory and pass it to the CachingConnectionFactory (Having of course no clue where the difference is but that is the case most of the time with spring):
@Bean
public ConnectionFactory connectionFactory() {
com.rabbitmq.client.ConnectionFactory connectionFactory = new com.rabbitmq.client.ConnectionFactory();
connectionFactory.setConnectionTimeout(this.connectionTimeout);
connectionFactory.setHost(this.rabbitHost);
connectionFactory.setPort(this.rabbitPort);
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(
connectionFactory);
return cachingConnectionFactory;
}
Now I can set the timeout to 1 during my acceptence tests causing the consumer initialization to fail quickly and to a higher value for deployment.
If the property spring.rabbitmq.listener.simple.auto-startup=false
does not have effect, you might be defining your own SimpleRabbitListenerContainerFactory
bean
Check how this bean is defined in the RabbitAnnotationDrivenConfiguration.rabbitListenerContainerFactory()
The SimpleRabbitListenerContainerFactoryConfigurer
binds together theSimpleRabbitListenerContainerFactory
and properties defined in your application.properties
(among other things)
If you use your own definition, then be sure to use something along the lines of
@Bean
SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
SimpleRabbitListenerContainerFactoryConfigurer containerFactoryConfigurer,
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory listenerContainerFactory =
new SimpleRabbitListenerContainerFactory();
containerFactoryConfigurer.configure(listenerContainerFactory, connectionFactory);
return listenerContainerFactory;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With