0
votes

My app has 2 rabbit instances it needs to connect to.

Rabbit1 is an entry point to my app, where my listener waits for message and

@RabbitListener(queues = "#{myAmqpProperties.getRequest().getQueue()}")

it is configured through regular Springboot2 properties

spring:
  rabbitmq:
    host: localhost
    username: myUser
    password: myPass
    port: 5672
    virtual-host: myVhost

This works fine.


Now I need to send rabbit message on another rabbitMQ instance, Rabbit2. So I created a configuration class building the rabbitTemplete and its associated connectionFactory.

package com.mycompany.socle.amqp.ocr;

import com.mycompany.doccontrol.messaging.app.AppMessageConverter;
import com.mycompany.socle.amqp.common.service.CpyAmqpRequestWithReplyToProp;
import com.mycompany.socle.amqp.common.service.CpyAmqpServerProperties;
import com.mycompany.socle.common.bean.SslProperties;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.validation.Valid;

@Configuration
@EnableRabbit
public class OcrAmqpConfiguration {


    @Autowired
    private OcrAmqpProperties ocrAmqpProperties;

    /**
     * Template used to send analysis request.
     *
     * @return the template to use
     * @throws Exception if there are issues while initialising the connection factory.
     */
    @Bean
    public RabbitTemplate appRequestTemplate() throws Exception {
        final RabbitTemplate rabbitTemplate = new RabbitTemplate(ocrConnectionFactory());
        rabbitTemplate.setMessageConverter(new AppMessageConverter());
        @Valid final CpyAmqpRequestWithReplyToProp appProperties = ocrAmqpProperties.getApp().getRequest();
        // Settings to send the request
        rabbitTemplate.setExchange(appProperties.getExchange());
        if (appProperties.getRoutingKey() != null) {
            rabbitTemplate.setRoutingKey(appProperties.getRoutingKey());
        }
        return rabbitTemplate;
    }

    /**
     * Define the Connection factory used to contact the broker.
     *
     * @return the connection factory
     * @throws Exception if there are issues while defining the factory context.
     */
    @Bean
    public CachingConnectionFactory ocrConnectionFactory() throws Exception {
        final CachingConnectionFactory result = new CachingConnectionFactory(builConnectionFactory(ocrAmqpProperties.getRabbitmq()).getObject());
        result.afterPropertiesSet();

        return result;
    }


    private static RabbitConnectionFactoryBean builConnectionFactory(MyAmqpServerProperties pAmqpProperties) {
        RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();

        // Generic connection properties
        factory.setHost(pAmqpProperties.getHost());
        factory.setPort(pAmqpProperties.getPort());
        factory.setUsername(pAmqpProperties.getUsername());
        factory.setPassword(pAmqpProperties.getPassword());
        factory.setVirtualHost(pAmqpProperties.getVirtualHost());

        factory.afterPropertiesSet();

        return factory;
    }

}

The class MyAmqpServerProperties is just a property class matching extra property i added in my property file to define Rabbit2 info.

But then the default SpringBoot ConnectionFactory is NOT generated, and my listener which listened originaly to Rabbit1, now also listen to Rabbit2.

I see RabbitAutoConfiguration java doc says:

  • Registers the following beans: * *
  • {@link org.springframework.amqp.rabbit.core.RabbitTemplate RabbitTemplate} if there * is no other bean of the same type in the context.
  • *
  • {@link org.springframework.amqp.rabbit.connection.CachingConnectionFactory * CachingConnectionFactory} instance if there is no other bean of the same type in the * context.

And in the code there is the annotation

@ConditionalOnMissingBean(ConnectionFactory.class)

=> If I remove the @Bean of the ocrConnectionFactory method, it works fine, however I need to have the ocrConnectionFactory registered in spring context for monitoring ... So is there a way to either register it AFTER the default one has been generated, or some other properties to force the default one to be generated as normal ?

1

1 Answers

1
votes

No. Boot will only configure one if you haven't any. If you configure one you must configure both.