1. Configuration File (application.yml)
spring:
rabbitmq:
primary:
host: localhost
port: 5672
username: guest
password: guest
virtualHost: /channel-demo
secondary:
host: 192.168.1.184
port: 5672
username: guest
password: guest
virtualHost: /third-party-test
2. Configuration Classes
Both configuration classes extend a shared abstract base class that provides the connectionFactory() method using the prefix defined by @ConfigurationProperties.
Base Configuration
// AbstractRabbitConfig.java (not shown in original but implied)
// It should use RabbitProperties or manual connection creation via CachingConnectionFactory.
// For brevity, assume it reads properties and returns a CachingConnectionFactory.
Primary RabbitMQ Configuraton
@Configuration
@ConfigurationProperties("spring.rabbitmq.primary")
public class PrimaryRabbitConfig extends AbstractRabbitConfig {
@Bean(name = "primaryConnectionFactory")
@Primary
public ConnectionFactory primaryConnectionFactory() {
return super.connectionFactory();
}
@Bean(name = "primaryRabbitTemplate")
@Primary
public RabbitTemplate primaryRabbitTemplate(
@Qualifier("primaryConnectionFactory") ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
@Bean(name = "primaryListenerContainerFactory")
public SimpleRabbitListenerContainerFactory primaryListenerFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer,
@Qualifier("primaryConnectionFactory") ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
@Bean(name = "primaryRabbitAdmin")
@Primary
public RabbitAdmin primaryRabbitAdmin(
@Qualifier("primaryConnectionFactory") ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareExchange(primaryExchange());
admin.declareQueue(primaryQueue());
admin.declareBinding(primaryBinding());
return admin;
}
@Bean
public DirectExchange primaryExchange() {
return new DirectExchange("primary-direct-exchange");
}
@Bean
public Queue primaryQueue() {
return new Queue("primary-queue");
}
@Bean
public Binding primaryBinding() {
return BindingBuilder.bind(primaryQueue()).to(primaryExchange()).with("primary-routing-key");
}
}
Secondary RabbitMQ Configuration
@Configuration
@ConfigurationProperties("spring.rabbitmq.secondary")
public class SecondaryRabbitConfig extends AbstractRabbitConfig {
@Bean(name = "secondaryConnectionFactory")
public ConnectionFactory secondaryConnectionFactory() {
return super.connectionFactory();
}
@Bean(name = "secondaryRabbitTemplate")
public RabbitTemplate secondaryRabbitTemplate(
@Qualifier("secondaryConnectionFactory") ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
@Bean(name = "secondaryListenerContainerFactory")
public SimpleRabbitListenerContainerFactory secondaryListenerFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer,
@Qualifier("secondaryConnectionFactory") ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
@Bean(name = "secondaryRabbitAdmin")
public RabbitAdmin secondaryRabbitAdmin(
@Qualifier("secondaryConnectionFactory") ConnectionFactory connectionFactory) {
RabbitAdmin admin = new RabbitAdmin(connectionFactory);
// Optionally declare secondary exchange/queue/binding if needed
// admin.declareExchange(...)
return admin;
}
}
3. Producer
Use the appropriate RabbitTemplate bean to send messsages to the primary RabbitMQ.
@Component
@Slf4j
public class MessageProducer {
@Autowired
@Qualifier("primaryRabbitTemplate")
private RabbitTemplate primaryTemplate;
public void sendPrimaryMessage() {
primaryTemplate.convertAndSend("primary-direct-exchange", "primary-routing-key", "Hello from primary");
log.info("Primary message sent successfully");
}
}
4. Consumer
Use @RabbitListener with the containerFactory attribute pointing to the specific listener factory bean.
@Component
@Slf4j
public class MessageConsumer {
@RabbitListener(queues = {"primary-queue"}, containerFactory = "primaryListenerContainerFactory")
@RabbitHandler
public void handlePrimaryMessage() {
System.out.println("Primary queue received a message");
}
// For secondary, define another listener if needed
// @RabbitListener(queues = {"secondary-queue"}, containerFactory = "secondaryListenerContainerFactory")
// @RabbitHandler
// public void handleSecondaryMessage() { ... }
}
With this setup, you can manage different RabbitMQ instances independently within the same Spring Boot application. The @Primary annotation ensures that the primary connection is used by default when no qualifier is specified, while the secondary instance can be accessed via explicit @Qualifier references.