Search code examples
spring-bootrabbitmqspring-amqp

rabbitConnectionFactory autodetected for JMX exposure


I have a Spring Boot application that supports Kafka. Recently I am trying to make it also support RabbitMQ. I set up the code using the @Profile annotation so that all the new code for RabbitMQ should be active only if I select spring.profiles.active to be rabbit-mq. Likewise, the Kafka-specific code are marked out by profile value of kafka

I was surprise to see that even with the above setup, when I set the profile to be kafka, some RabbitMQ is still included and activated, through a mechanism JMX exposure. Specifically, a rabbitConnectionFactory bean was constructed, and then it tried to do health check with a RabbitMQ broker at localhost:5672, and failed.

In the log file, I saw these messages:

... o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
... o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'rabbitConnectionFactory' has been autodetected for JMX exposure
... o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'rabbitConnectionFactory': registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory]
... o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483547
... o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
... o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
... c.s.datacomparatorproducer.Application   : Started Application in 5.175 seconds (JVM running for 5.663)
... o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
... o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
... o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 15 ms
... o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [localhost:5672]
... o.s.b.a.amqp.RabbitHealthIndicator       : Rabbit health check failed

org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused (Connection refused)
        at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]
        at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:476) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]
        at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:614) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]
        at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:240) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]
        at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1797) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]
        at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1771) ~[spring-rabbit-2.0.3.RELEASE.jar!/:2.0.3.RELEASE]

I have two questions:

  1. How can I avoid RabbitMQ code from being included? Why my set up using @Profile did not work as expected?
  2. How do I configure the rabbitConnectionFactory? Currently it is trying to talk to localhost:5672. I know how to, in general, set up Spring template to use application-xxx.properties for spring.rabbitmq.{host,port}, but in this case, since the code is auto-included, I don't know how to configure rabbitConnectionFactory

Usual configuration

spring.rabbitmq.host=someRabbitBroker
spring.rabbitmq.port=5672

Update

Attempt 1: Excluding RabbitAutoConfiguration

Thank you Gary Russell for the suggestion. I tried his method and changed my @SpringBootApplication as follows. The idea here is to exclude RabbitAutoConfiguration when spring.rabbitmq.host is NOT defined (when the profile of rabbit-mq is not active):

@SpringBootApplication
public class Application {

    @ConditionalOnProperty(value="spring.rabbitmq.host")
    @Bean 
    RabbitAutoConfiguration rabbitAutoConfiguration(){
        return new RabbitAutoConfiguration();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

I am not sure if this code is the correct way to do it, but it did not work. When my app started, I still saw these in the message:

... o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
... o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'rabbitConnectionFactory' has been autodetected for JMX exposure
... o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean 'rabbitConnectionFactory': registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory]
... o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483547

I am okay with having the bean constructed, as long as I can stop it from doing health check (or at least configure it to use my designated host and port). Is there a way to do this?


Solution

  • You either need to exclude the spring-rabbit jar from the classpath or disable rabbitmq auto-configuration by excluding RabbitAutoConfiguration from the @SpringBootApplication.

    Update: disabling health check

    See the boot properties documentation. Specifically set management.health.rabbit.enabled to false