0
votes

We are using Spring Boot for our application. After starting the application, in the runtime we are adding(loading) a new Bean to the existing Applicationcontext.

AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
appContext.register(NewBean.class);
appContext.refresh();

after adding the bean we are doing a refresh of applicationContext

During the refresh the MBean is trying to reregister some endpoints and we are getting the following error (getting error for all these endpoints - requestMappingEndpoint, environmentEndpoint, healthEndpoint, beansEndpoint, infoEndpoint, metricsEndpoint, traceEndpoint, dumpEndpoint, autoConfigurationAuditEndpoint, shutdownEndpoint, configurationPropertiesReportEndpoint)

Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Endpoint,name=configurationPropertiesReportEndpoint
        at com.sun.jmx.mbeanserver.Repository.addMBean(Unknown Source)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(Unknown Source)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(Unknown Source)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(Unknown Source)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(Unknown Source)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(Unknown Source)
        at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195)
        at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:662)
        at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:605)

Can anyone please tell how to skip this exception?

I have tried the following too

@EnableIntegrationMBeanExport(registration = RegistrationPolicy.REPLACE_EXISTING)

but getting the below exception

Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.springframework.integration.monitor.IntegrationMBeanExporter@16c5464] with key 'integrationMbeanExporter'; nested exception is javax.management.InstanceAlreadyExistsException: org.springframework.integration.monitor:name=integrationMbeanExporter,type=IntegrationMBeanExporter
    at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:609)
    at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:534)
    at org.springframework.jmx.export.MBeanExporter.afterPropertiesSet(MBeanExporter.java:416)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 22 more
Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.integration.monitor:name=integrationMbeanExporter,type=IntegrationMBeanExporter
    at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:437)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1898)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:966)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
    at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195)
    at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:662)
    at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:599)
    ... 26 more
2
You should first destroy it else beans keep running. Why do you need to add beans add runtime? What you show here is that you are constructing a new context so not sure what you think should happen? The register method is also intended for configuration classes not arbitrary beans, if you want to add those just use one of the methods on the ApplicationContext like, registerSingleton. But in general adding beans at runtime should be a bad thing (imho). - M. Deinum
@M.Deinum This qualifies as an answer, rather than a comment. - Costi Ciudatu

2 Answers

0
votes

Before you call refresh on an existing ApplicationContext, you should first destroy it else beans keep running.

AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
appContext.register(NewBean.class);
appContext.refresh();

What you show here is that you are constructing a new context instead of reusing an existing one. The register method is also intended for @Configuration classes not arbitrary beans. If you want to add those just use one of the methods on the ApplicationContext like, registerSingleton. But in general adding beans at runtime should be a bad thing (imho).

0
votes

Some applicationContext can refresh times, but not AnnotationConfigApplicationContext. when you construct AnnotationConfigApplicationContext, which had run the refresh method, so it will be reported exception, you can destroy it first, and then refresh