'Spring AMQP - RabbitMQ connection is not created on application startup
I have a Spring Boot application and my goal is to declare queues, exchanges, and bindings on application startup. The application will produce messages to various queues there will be no consumers on the application.
I have included those dependencies on my pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.2.12.RELEASE</version>
</dependency>
my configuration class
@Configuration
public class RabbitConfiguration {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("myhost", 5672);
connectionFactory.setUsername("example_name");
connectionFactory.setPassword("example_pass");
return connectionFactory;
}
@Bean
public AmqpAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
@Bean
public Queue declareQueue() {
return new Queue("test_queue", true, false, false);
}
@Bean
public DirectExchange declareDirectExchange() {
return new DirectExchange("test_direct_exchange", true, false);
}
@Bean
public Declarables declareBindings() {
return new Declarables(
new Binding("test_queue", DestinationType.QUEUE, "test_direct_exchange", "test_routing_key", null)
);
}
}
My problem is that queues, exchanges, and bindings are not created on the application startup. Spring boot does not even open the connection. The connection, queues, etc are created only when I produce messages to the queues.
Solution 1:[1]
If you want to force declaration during app startup and don't have any consumers, you can either add the actuator starter to the classpath, or simply create the shared connection yourself.
@Bean
ApplicationRunner runner(ConnectionFactory cf) {
return args -> cf.createConnection().close();
}
This won't close the connection; if you want to do that, call cf.resetConnection()
.
If you want the app to start if the broker is down, do something like this.
@Bean
ApplicationRunner runner(ConnectionFactory cf) {
return args -> {
boolean open = false;
while(!open) {
try {
cf.createConnection().close();
open = true;
}
catch (Exception e) {
Thread.sleep(5000);
}
}
};
}
Solution 2:[2]
After some digging, I have found out that I was missing the actuator dependency. So adding this dependency solved my issue
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
It is weird that the connection is not opened on application startup unless the actuator dependency is present.
Solution 3:[3]
You can use
@Component
public class QueueConfig {
private AmqpAdmin amqpAdmin;
public QueueConfig(AmqpAdmin amqpAdmin) {
this.amqpAdmin = amqpAdmin;
}
@PostConstruct
public void createQueues() {
amqpAdmin.declareQueue(new Queue("q1", true));
amqpAdmin.declareQueue(new Queue("q2", true));
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Gary Russell |
Solution 2 | Thanos M |
Solution 3 | walkwolf |