Mbean named conflict when climbing two Spring Boot applications in the same Tomcat

Asked

Viewed 121 times

3

I have two applications in Spring Boot that use a common nomenclature for Beans. In case, man pool of connections to the database is managed by Hikaricp.

Due to an infrastructure problem, I had to upload two of my Spring Boot projects to the same Tomcat. By trying to do this, Tomcat returns this error to me:

org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [com.zaxxer.hikari.HikariConfig@60a88c19] with key 'myHikariConfig'; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=myHikariConfig,type=HikariConfig
  at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:628) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:550) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:432) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:781) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  ... 37 frames omitidos
Caused by: javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=myHikariConfig,type=HikariConfig
  at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:437) ~[na:1.8.0_151]
  at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1898) ~[na:1.8.0_151]
  at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:966) ~[na:1.8.0_151]
  at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900) ~[na:1.8.0_151]
  at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324) ~[na:1.8.0_151]
  at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) ~[na:1.8.0_151]
  at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:674) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:618) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
  ... 42 common frames omitted

2018-04-18 16:09:08.482  INFO 1412 --- [           main] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@271c4: startup date [Wed Apr 18 16:08:51 GFT 2018]; root of context hierarchy
2018-04-18 16:09:08.482  INFO 1412 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

I know I could treat by renaming the Beans of both projects not to clash, but there are several others Beans that also follow the naming pattern, just as there are other applications in Spring Boot here in the company that occasionally we will need to climb (possibly) in the same Tomcat.

So you have to isolate each application to have a kind of "namespace" of Beans in the Spring? If yes, how?

I’m looking for an alternative that minimizes code changes.

1 answer

4


Yes. By setting the JMX domain name you get a kind of "isolation" by setting a JMX domain name. You can check the property spring.jmx.default-domain in the documentation. This response in the international SO exemplifies how to treat this.

In this case, I only had to define for each application a different JMX domain name, not being necessary no other action. I just needed to add the following lines to my application.properties for the application 1:

spring.application.name=myFirstApp
spring.jmx.default-domain=myFirstApp

And for the other application:

spring.application.name=mySecondApp
spring.jmx.default-domain=mySecondApp

We even used another variable in the application.properties that made the times of application identifier to recover in a customized way the tenant routing datasource of Hikaricp, called mybootapp.appname. So, in fact, the change was just to put the following lines in the application.properties:

spring.application.name=${mybootapp.appname}
spring.jmx.default-domain=${mybootapp.appname}

Thus, the application.properties remained:

mybootapp.appname=myFirstApp
spring.application.name=${mybootapp.appname}
spring.jmx.default-domain=${mybootapp.appname}
mybootapp.appname=mySecondApp
spring.application.name=${mybootapp.appname}
spring.jmx.default-domain=${mybootapp.appname}

This was the alternative with less changes that I found, without having to touch the settings of container.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.