While working on a project with multi spring context (one parent and multi child) to expose actuators.

@SpringBootApplication(scanBasePackages = {"com.test.parent.app"})
public class ReproduceApplication {

    public static void main(String[] args) {
        SpringApplicationBuilder app =
                new SpringApplicationBuilder(ReproduceApplication.class)
                        .bannerMode(Banner.Mode.LOG)
                        .web(WebApplicationType.NONE);

        app.run(args);


        app.child(ChildOneApplication.class)
                .profiles("one")
                .web(WebApplicationType.SERVLET)
                .bannerMode(Banner.Mode.OFF)
                .run(args);

        app.child(ChildTwoApplication.class)
                .web(WebApplicationType.NONE)
                .profiles("two")
                .bannerMode(Banner.Mode.OFF)
                .run(args);

    }
}

@SpringBootApplication(scanBasePackages = {"com.test.child.one"})
@EnableWebMvc
public class ChildOneApplication {

}


@SpringBootApplication(scanBasePackages = {"com.test.child.two"})
public class ChildTwoApplication {
}

spring-boot-actuator-2.6.5

It occurs the javax.management.InstanceAlreadyExistsException.

Connected to the target VM, address: '127.0.0.1:62526', transport: 'socket'
2022-07-14 17:11:23.299  INFO 8565 --- [           main] o.s.boot.SpringApplication               : 
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.5)


2022-07-14 17:11:23.341  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : Starting ReproduceApplication using Java 11.0.2 ...
2022-07-14 17:11:23.342  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : No active profile set, falling back to 1 default profile: "default"
2022-07-14 17:11:24.185  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : Started ReproduceApplication in 1.15 seconds (JVM running for 1.885)
2022-07-14 17:11:24.220  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : The following 1 profile is active: "one"
2022-07-14 17:11:24.717  INFO 8565 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 10010 (http)
2022-07-14 17:11:24.725  INFO 8565 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-07-14 17:11:24.725  INFO 8565 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.60]
2022-07-14 17:11:24.819  INFO 8565 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-07-14 17:11:24.819  INFO 8565 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 596 ms
2022-07-14 17:11:25.027  INFO 8565 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2022-07-14 17:11:25.061  INFO 8565 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 10010 (http) with context path ''
2022-07-14 17:11:25.070  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : Started ReproduceApplication in 0.88 seconds (JVM running for 2.771)
2022-07-14 17:11:25.102  INFO 8565 --- [           main] c.test.parent.app.ReproduceApplication   : The following 1 profile is active: "two"
2022-07-14 17:11:25.234  WARN 8565 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmxMBeanExporter' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jmx.export.MBeanExportException: Failed to register MBean for endpoint 'beans'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Endpoint,name=Beans,context=7e38a7fe
2022-07-14 17:11:25.242  INFO 8565 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-07-14 17:11:25.263 ERROR 8565 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmxMBeanExporter' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jmx.export.MBeanExportException: Failed to register MBean for endpoint 'beans'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Endpoint,name=Beans,context=7e38a7fe
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.17.jar:5.3.17]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.17.jar:5.3.17]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.5.jar:2.6.5]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.5.jar:2.6.5]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.5.jar:2.6.5]
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) ~[spring-boot-2.6.5.jar:2.6.5]
    at com.test.parent.app.ReproduceApplication.main(ReproduceApplication.java:35) ~[classes/:na]
Caused by: org.springframework.jmx.export.MBeanExportException: Failed to register MBean for endpoint 'beans'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Endpoint,name=Beans,context=7e38a7fe
    at org.springframework.boot.actuate.endpoint.jmx.JmxEndpointExporter.register(JmxEndpointExporter.java:105) ~[spring-boot-actuator-2.6.5.jar:2.6.5]
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
    at org.springframework.boot.actuate.endpoint.jmx.JmxEndpointExporter.register(JmxEndpointExporter.java:90) ~[spring-boot-actuator-2.6.5.jar:2.6.5]
    at org.springframework.boot.actuate.endpoint.jmx.JmxEndpointExporter.afterPropertiesSet(JmxEndpointExporter.java:81) ~[spring-boot-actuator-2.6.5.jar:2.6.5]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.17.jar:5.3.17]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.17.jar:5.3.17]
    ... 14 common frames omitted
Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Endpoint,name=Beans,context=7e38a7fe
    at java.management/com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:436) ~[na:na]
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1855) ~[na:na]
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:955) ~[na:na]
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:890) ~[na:na]
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:320) ~[na:na]
    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) ~[na:na]
    at org.springframework.boot.actuate.endpoint.jmx.JmxEndpointExporter.register(JmxEndpointExporter.java:98) ~[spring-boot-actuator-2.6.5.jar:2.6.5]
    ... 26 common frames omitted

I found each time scan and exposed endpoints use the same org.springframework.boot.actuate.autoconfigure.endpoint.jmx.DefaultEndpointObjectNameFactory with same contextId, which will generate the same ObjectName.

    @Bean
    @ConditionalOnMissingBean({EndpointObjectNameFactory.class})
    public DefaultEndpointObjectNameFactory endpointObjectNameFactory(MBeanServer mBeanServer, Environment environment) {
       // It only set once with the parent context as a singleton, although it has been changed to child's application context.
        String contextId = ObjectUtils.getIdentityHexString(this.applicationContext);
        return new DefaultEndpointObjectNameFactory(this.properties, environment, mBeanServer, contextId);
    }

    @Bean
    @ConditionalOnSingleCandidate(MBeanServer.class)
    public JmxEndpointExporter jmxMBeanExporter(MBeanServer mBeanServer, EndpointObjectNameFactory endpointObjectNameFactory, ObjectProvider<ObjectMapper> objectMapper, JmxEndpointsSupplier jmxEndpointsSupplier) {
        JmxOperationResponseMapper responseMapper = new JacksonJmxOperationResponseMapper((ObjectMapper)objectMapper.getIfAvailable());
        // it always use the DefaultEndpointObjectNameFactory with parent contextId.
        return new JmxEndpointExporter(mBeanServer, endpointObjectNameFactory, responseMapper, jmxEndpointsSupplier.getEndpoints());
    }

So I just create my own EndpointObjectNameFactory bean to provide unique ObjectName, everything works fine.

@Component
public class CustomEndpointFactory implements EndpointObjectNameFactory {
    @Override
    public ObjectName getObjectName(ExposableJmxEndpoint endpoint) throws MalformedObjectNameException {
        StringBuilder builder = new StringBuilder();
        builder.append(":type=Endpoint");
        builder.append(",name=").append(StringUtils.capitalize(endpoint.getEndpointId().toString()));
        builder.append(",unique=").append(UUID.randomUUID().toString());
        return ObjectNameManager.getInstance(builder.toString());
    }
}

I guess it seems like register the same bean twice like this one #6378.

Comment From: ilharp

I've ran into the same problem using spring-boot-actuator:2.7.1, thanks for the temporary workaround!

Besides, I found that modifying spring.jmx.unique-names, management.endpoints.jmx.domain or management.endpoints.jmx.static-names has no effect - all bean factories try to load using the parent application's configuration. If the actuator can identify the currently loaded (child) application, then adding some fields like "application-unique id" inside the EndpointObjectNameFactory will be simple. Will this be implemented later?