java - info - Error al anular el registro del MBS de DataSource JMX al cerrar una aplicación Spring Boot
spring boot info endpoint (4)
Tengo una aplicación Spring Boot simple que utiliza org.apache.commons.dbcp2.BasicDataSource como bean DataSource.
El origen de datos se expone como MBean automáticamente por Spring Boot.
La declaración de frijol:
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(dbUrl);
dataSource.setDriverClassName(jdbcDriver);
dataSource.setUsername(dbUserName);
dataSource.setPassword(dbPassword);
return dataSource;
}
Todo funciona bien. Sin embargo, veo un error al cerrar la aplicación. Este error solo ocurre al ejecutar el jar ejecutable. Cuando se utiliza el complemento Gradle Spring (gradle bootRun), esto no se muestra.
javax.management.InstanceNotFoundException: org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1095)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.exclusiveUnregisterMBean(DefaultMBeanServerInterceptor.java:427)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.unregisterMBean(DefaultMBeanServerInterceptor.java:415)
at com.sun.jmx.mbeanserver.JmxMBeanServer.unregisterMBean(JmxMBeanServer.java:546)
at org.apache.commons.dbcp2.BasicDataSource.close(BasicDataSource.java:1822)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.beans.factory.support.DisposableBeanAdapter.invokeCustomDestroyMethod(DisposableBeanAdapter.java:350)
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:273)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:540)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:516)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:827)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:485)
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:921)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:895)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.doClose(EmbeddedWebApplicationContext.java:152)
at org.springframework.context.support.AbstractApplicationContext$1.run(AbstractApplicationContext.java:809)
Me pregunto: 1. ¿Cómo se expone este bean como JMX MBean? 2. ¿Cómo anular correctamente el registro de este MBean?
Spring está intentando cerrar BasicDataSource dos veces:
- BasicDataSource se cierra automáticamente cuando se cierra la aplicación
- Spring usa el método de destrucción predeterminado para cerrar DataSource pero ya está cerrado
Para evitar esto, use:
@Bean(destroyMethod = "")
public DataSource dataSource()
En su configuración de Java
Tuve el mismo problema. Agregar un servidor MBean y registrar el origen de datos tampoco puede arreglarlo.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jmx.html
Mi conclusión es que el BasicDataSource de DBCP2 tiene un error al anular el registro del servidor MBean.
Arreglé la mía cambiando a c3p0 de mchange: http://www.mchange.com/projects/c3p0/
Tuve el mismo problema. c3p0 funciona muy bien.
si se utiliza spring framework
- pom.xml
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
inicialmente utilizado
DataSource ds_unpooled = DataSources.unpooledDataSource(persistenceUrl,
persistenceUsername,
persistencePassword);
return DataSources.pooledDataSource(ds_unpooled);
pero no pudo manejar la carga que necesito realizar y cambié a la siguiente
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( persistenceDriver ); //loads the jdbc driver
cpds.setJdbcUrl( persistenceUrl );
cpds.setUser(persistenceUsername);
cpds.setPassword(persistencePassword);
cpds.setMinPoolSize(5);
cpds.setMaxPoolSize(50);
cpds.setUnreturnedConnectionTimeout(1800);
cpds.setMaxStatements(50);
cpds.setMaxIdleTime(21600);
cpds.setIdleConnectionTestPeriod(10800);
return cpds;
esos valores son de otras publicaciones que he reunido en línea.
en mi experiencia para mi tarea específica, ejecutar c3p0 se realiza más rápido que dbcp2 v: 2.1.1 en el mismo entorno.
Espero que esto ayude un poco. ¡aclamaciones!
BasicDataSource extends BasicDataSourceMXBean
, por lo que se registra automáticamente con el servidor JMX como MBean [org.apache.commons.dbcp2:name=dataSource,type=BasicDataSource]
. Cuando Springboot se detiene, MBeanExporter anula el registro del MBean, luego springboot intenta destruir BasicDataSource
, y llama al método BasicDataSource close()
, anula el registro del MBean nuevamente (BasicDataSource detecta la excepción JMException e imprime esta advertencia). Es solo una advertencia. Si no desea imprimirlo, puede desactivar JMX en springboot.
application.yml
spring:
jmx:
enabled: false