迁移到Tomcat 8:InstanceAlreadyExistsException数据源

时间:2015-02-03 09:32:07

标签: java tomcat configuration context.xml

我在Tomcat 8中有关于上下文配置的问题。我将项目从Tomcat 7迁移到8并且有异常问题:如果配置中没有任何更改我发现错误:

    "2015-02-03 12:05:48,310 FIRST_ADMIN ERROR web.context.ContextLoader:331 
-> Context initialization failed org.springframework.jmx.export.UnableToRegisterMBeanException: 
    Unable to register MBean [org.apache.tomcat.dbcp.dbcp2.BasicDataSource@434990dd]
     with key 'dataSource'; nested exception is 
    javax.management.InstanceAlreadyExistsException:  
    Catalina:type=DataSource,host=localhost,context=/first-
    admin,class=javax.sql.DataSource,name="jdbc/datasource/first"

上下文的一部分:

<Resource name="jdbc/datasource/first"
              auth="Container"
              type="javax.sql.DataSource"
              poolPreparedStatements="true"
              initialSize="25"
              maxActive="100"
              maxIdle="100"
              minIdle="25"
              username="us"
              password="pa"
              driverClassName="com.mysql.jdbc.Driver"
              validationQuery="select 1"
              testOnBorrow="true"
          url="jdbc:mysql://localhost:3306/firstproject?useUnicode=true&amp;characterEncoding=UTF-8&amp;profileSQL=false&amp;autoSlowLog=false&amp;slowQueryThresholdMillis=100&amp;autoReconnect=true"/>

所以,它在tomcat 7中运行没有任何问题。在Tomcat 8中,我可以通过两种方式解决这个问题:

  1. 添加到资源:singleton = "false";
  2. 添加到资源:factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
  3. 如果我清楚地了解tomcat为我的应用程序和jmx创建数据源,但在Tomcat 7中它是单个对象,在Tomcat 8中它必须是不同的。所以我的问题是为什么会出现这种情况?我在文档中找不到任何有关此更改的信息。我觉得更好的是:创建单个数据源(我想是这样)或者按工厂创建几个。

5 个答案:

答案 0 :(得分:10)

我们遇到了同样的问题。我们将我们的数据源声明为一个spring bean,看起来spring和bean本身都试图注册一个导致这种冲突的Mbean。 我们所要做的就是像这样配置我们的Mbean Exporter:

@Bean
public AnnotationMBeanExporter annotationMBeanExporter() {
    AnnotationMBeanExporter annotationMBeanExporter = new AnnotationMBeanExporter();
    annotationMBeanExporter.addExcludedBean("dataSource");
    return annotationMBeanExporter;
}

虽然我认为将注册政策设置为:

annotationMBeanExporter.setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);

也可能有用。

答案 1 :(得分:8)

我遇到了同样的错误并通过将 registration =&#34; ignoreExisting&#34; 添加到mbean-export部分来解决它:

<context:mbean-export server="mbeanServer" default-domain="mydomain" registration="ignoreExisting" />

答案 2 :(得分:4)

如果您希望解决方案使用注释 Spring引导已经定义了 MBeanExporter bean,因此您可以自动连接它

@Autowired
MBeanExporter mBeanExporter ;

然后更改注册政策

mBeanExporter.setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);

答案 3 :(得分:1)

如果有人在那里使用 applicationContext.xml 样式,我将解决以下问题:

<bean id="myNamedExporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="registrationPolicy" value="IGNORE_EXISTING" />
</bean>

答案 4 :(得分:0)

有一个聪明的简单方法可以避免此问题。

将数据源定义放到生产服务器上某个位置的application.properties文件中。 例如:

zip

并将此行添加到xml上下文中

datasource.driverClassName=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost:3306/firstproject?useUnicode=true&amp;characterEncoding=UTF-8&amp;profileSQL=false&amp;autoSlowLog=false&amp;slowQueryThresholdMillis=100&amp;autoReconnect=true
datasource.username=us
etc..

在这里How to externalize application.properties in Tomcat webserver for Spring?

找到解决方案之前,我一直很努力。

它将为您带来其他优势:

  • 简单的弹簧配置
  • 允许您使用嵌入式tomcat运行网络应用
  • 如果您无意中将自己的application.properties打包在war文件中,则生产tomcat将忽略它