NutzCN Logo
问答 junit测试多数据源,ioc执行depose抛出unregister mbean error
发布于 2304天前 作者 seasongithub 1651 次浏览 复制 上一个帖子 下一个帖子
标签: nutzwk

定义了两个数据源:

#mysql
db.name=jmsmall
db.url=jdbc:mysql://127.0.0.1:3306/jmsmall?useUnicode=true&characterEncoding=utf8&useSSL=false
db.username=root
db.password=123456
db.validationQuery=select 1
db.maxActive=100
db.testWhileIdle=true
db.filters=mergeStat
db.connectionProperties=druid.stat.slowSqlMillis=2000
db.defaultAutoCommit=true

db2.name=jmsmall
db2.url=jdbc:mysql://127.0.0.1:3306/jms?useUnicode=true&characterEncoding=utf8&useSSL=false
db2.username=root
db2.password=123456
db2.validationQuery=select 1
db2.maxActive=100
db2.testWhileIdle=true
db2.filters=mergeStat
db2.connectionProperties=druid.stat.slowSqlMillis=2000
db2.defaultAutoCommit=true
dataSource : {
			factory : "$conf#make",
			args : ["com.alibaba.druid.pool.DruidDataSource", "db."],
	        type : "com.alibaba.druid.pool.DruidDataSource",
	        events : {
	        	create : "init",
	            depose : 'close'
	        }
	    },
		dao : {
			type : "org.nutz.dao.impl.NutDao",
			args : [{refer:"dataSource"}],
			fields : {
				executor : {refer:"cacheExecutor"}
			}
		},

		dataSource2 : {
			factory : "$conf#make",
			args : ["com.alibaba.druid.pool.DruidDataSource", "db2."],
			type : "com.alibaba.druid.pool.DruidDataSource",
			events : {
				create : "init",
				depose : 'close'
			}
		},
		dao2 : {
			type : "org.nutz.dao.impl.NutDao",
			args : [{refer:"dataSource2"}],
		},

测试用例如下:

package cn.wizzer.test;

import cn.wizzer.app.web.commons.core.Module;
import net.sf.ehcache.CacheManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.IocLoader;
import org.nutz.ioc.impl.NutIoc;
import org.nutz.ioc.loader.combo.ComboIocLoader;
import org.nutz.mvc.annotation.IocBy;

public class TestMultipleDataSource {
    protected Ioc ioc;
    protected Dao dao;
    protected Dao dao2;

    @Before
    public void before() throws Exception {
        CacheManager.getInstance();
        IocBy iocBy = Module.class.getAnnotation(IocBy.class);
        IocLoader loader = new ComboIocLoader(iocBy.args());
        ioc = new NutIoc(loader);
        dao = ioc.get(Dao.class);
        dao2 = ioc.get(Dao.class, "dao2");
    }

    @After
    public void after() throws Exception {
        if (ioc != null) {
            ioc.depose();
        }
    }

    /**
     * 测试多数据源
     */
    @Test
    public void test_dataSource() {
         Sql sql = Sqls.create("select database()");
         sql.setCallback(Sqls.callback.str());
         dao.execute(sql);
         String database = sql.getString();
         System.out.println("first dataSource:" + database);

        Sql sql2 = Sqls.create("select database()");
        sql2.setCallback(Sqls.callback.str());
        dao2.execute(sql2);
        String database1 = sql2.getString();
        System.out.println("second dataSource:" + database1);
    }
}

执行抛出如下异常:

[DEBUG] 2017-12-06 15:41:13,906 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) - select database()
first dataSource:jmsmall
[DEBUG] 2017-12-06 15:41:13,911 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) - select database()
second dataSource:jms
[INFO ] 2017-12-06 15:41:13,915 org.nutz.ioc.impl.NutIoc.depose(NutIoc.java:261) - org.nutz.ioc.impl.NutIoc@2050370411 is closing. startup date [17-12-06 15:41:12.963]
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'dao2' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'cacheManager' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'cacheProvider' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'cacheExecutor' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'conf' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'dao' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_wkcache' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_syslog' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_slog' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_cuxlog' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_async' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object 'dynamicInterceptor' ...
[DEBUG] 2017-12-06 15:41:13,916 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:108) - Depose object '$aop_1_plugin' ...
[DEBUG] 2017-12-06 15:41:13,917 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:113) - Depose object 'dataSource2' ...
[INFO ] 2017-12-06 15:41:13,919 com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1514) - {dataSource-2} closed
[DEBUG] 2017-12-06 15:41:13,919 org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:113) - Depose object 'dataSource' ...
[ERROR] 2017-12-06 15:41:13,920 com.alibaba.druid.stat.DruidDataSourceStatManager.removeDataSource(DruidDataSourceStatManager.java:192) - unregister mbean error
javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidDataSource,id=jmsmall
	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 com.alibaba.druid.stat.DruidDataSourceStatManager.removeDataSource(DruidDataSourceStatManager.java:190)
	at com.alibaba.druid.pool.DruidDataSource$2.run(DruidDataSource.java:1542)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.alibaba.druid.pool.DruidDataSource.unregisterMbean(DruidDataSource.java:1538)
	at com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1497)
	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:498)
	at org.nutz.ioc.trigger.MethodEventTrigger.trigger(MethodEventTrigger.java:18)
	at org.nutz.ioc.ObjectProxy.depose(ObjectProxy.java:83)
	at org.nutz.ioc.impl.ScopeContext.clear(ScopeContext.java:114)
	at org.nutz.ioc.impl.ScopeContext.depose(ScopeContext.java:121)
	at org.nutz.ioc.impl.NutIoc.depose(NutIoc.java:271)
	at cn.wizzer.test.TestMultipleDataSource.after(TestMultipleDataSource.java:35)
	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:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
[INFO ] 2017-12-06 15:41:13,921 com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1514) - {dataSource-1} closed

请问大神应该如何排查?

7 回复

看上去像是druid的bug?

两个数据源如果是MySQL和oracle,测试用例执行没有问题;
如果两个数据源都是mysql,而且type都是DruidDataSource,是否在关闭第一个mysql数据源的时候,同时把DruidDataSource也关闭了?导致在关闭第二个mysql数据源的时候,DruidDataSource获取的只是一个空对象?

我测试了另一种情况:两个不同的mysql数据库,测试用例通过;
depose失败的两个mysql数据库是 一个数据库中的两个不同的实例;
MySQL是单进程多线程的,是否在配置连接池的时候,如果两个mysql数据库实例是一个数据库的,nutzwk只会维持一个连接池?如果释放了其中的一个数据库实例连接,是否会同时释放这个数据库的连接池?从而导致另一个数据库实例的连接池也已释放

我觉得你可以考虑一下这样测试

新建两个DruidDataSource对象,分别获取一次连接,然后逐一调用close,看看会不会报错

报了同样的错误,我的测试用例是:

/**
     * 根据dbBame创建DruidDataSource
     * @param dbBame
     * @return
     * @throws SQLException
     */
    public DruidDataSource createDruidDataSource(String dbBame) throws SQLException {
        DruidDataSource ds = new DruidDataSource();
        ds.setName("jmsmall");
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/" + dbBame + "?useUnicode=true&characterEncoding=utf8&useSSL=false");
        ds.setUsername("root");
        ds.setPassword("123456");
        ds.setValidationQuery("select 1");
        ds.setMaxActive(100);
        ds.setTestWhileIdle(true);
        ds.setFilters("mergeStat");
        Properties p1 = new Properties();
        p1.setProperty("druid.stat.slowSqlMillis", "2000");
        ds.setConnectProperties(p1);
        ds.setInitialSize(5);
        ds.setMinIdle(1);
        ds.setMaxActive(10);
        ds.setDefaultAutoCommit(true);
        return ds;
    }

    @Test
    public void test_DruidDataSource() throws SQLException {
        Dao dao_1 = null;
        Dao dao_2 = null;
        DruidDataSource ds_1 = createDruidDataSource("jmsmall");
        if (ds_1 != null) {
            dao_1 = new NutDao(ds_1);
        }
        DruidDataSource ds_2 = createDruidDataSource("jms");
        if (ds_2 != null) {
            dao_2 = new NutDao(ds_2);
        }

        if (dao_1 != null) {
            Sql sql_1 = Sqls.create("select database()");
            sql_1.setCallback(Sqls.callback.str());
            dao_1.execute(sql_1);
            System.out.println("first dataSource:" + sql_1.getString());
            ds_1.close();
        }

        if (dao_2 != null) {
            Sql sql_2 = Sqls.create("select database()");
            sql_2.setCallback(Sqls.callback.str());
            dao_2.execute(sql_2);
            System.out.println("first dataSource:" + sql_2.getString());
            ds_2.close();
        }
    }

异常是:

[DEBUG] 2017-12-06 17:09:18,250 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) - select database()
first dataSource:jmsmall
[INFO ] 2017-12-06 17:09:18,255 com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1514) - {dataSource-1} closed
[DEBUG] 2017-12-06 17:09:18,255 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) - select database()
first dataSource:jms
[ERROR] 2017-12-06 17:09:18,257 com.alibaba.druid.stat.DruidDataSourceStatManager.removeDataSource(DruidDataSourceStatManager.java:192) - unregister mbean error
javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidDataSource,id=jmsmall
	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 com.alibaba.druid.stat.DruidDataSourceStatManager.removeDataSource(DruidDataSourceStatManager.java:190)
	at com.alibaba.druid.pool.DruidDataSource$2.run(DruidDataSource.java:1542)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.alibaba.druid.pool.DruidDataSource.unregisterMbean(DruidDataSource.java:1538)
	at com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1497)
	at cn.wizzer.test.TestMultipleDataSource.test_DruidDataSource(TestMultipleDataSource.java:114)
	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:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
[INFO ] 2017-12-06 17:09:18,259 com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1514) - {dataSource-2} closed

奇怪的是,我先关闭的是jmsmall,后关闭的是jms;
而且执行ds_1.close();也没有异常,后续的代码还有执行;
但是异常抛出的提示却是jmsmall,想不通是为啥

哦,我的错,我的name是同一个...DruidDataSource应该是根据name来管理的

添加回复
请先登陆
回到顶部