迁移到 Tomcat 8:InstanceAlreadyExistsException 数据源
Posted
技术标签:
【中文标题】迁移到 Tomcat 8:InstanceAlreadyExistsException 数据源【英文标题】:Migration to Tomcat 8: InstanceAlreadyExistsException datasource 【发布时间】:2015-04-02 10:44:33 【问题描述】:我对 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&characterEncoding=UTF-8&profileSQL=false&autoSlowLog=false&slowQueryThresholdMillis=100&autoReconnect=true"/>
所以,它在 tomcat 7 中运行没有任何问题。在 Tomcat 8 中,我可以通过 2 种方式解决这个问题:
-
通过添加到资源:
singleton = "false";
通过添加到资源:factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
如果我清楚地了解 tomcat 为我的应用程序和 jmx 创建数据源,但在 Tomcat 7 中它是单个对象,在 Tomcat 8 中它必须不同。所以我的问题是为什么会发生这种情况?我在文档中找不到有关此更改的任何信息。而且我很感兴趣什么更好:创建单个数据源(我认为是这样)或通过工厂创建多个。
【问题讨论】:
tomcat 7 (from) 和 tomcat 8 (to) 的版本是什么?您还可以添加您的 web.xml 吗?您的应用程序是否在其自己的 context.xml 文件 (META-INF) 中使用上述声明 - 如果是,您可以发布这个吗?顺便说一句,使用 JDBC 资源时,单例必须为“true” 【参考方案1】:有一个聪明的简单方法可以避免这个问题。
将数据源定义放在生产服务器上某处的 application.properties 文件中。 例如:
datasource.driverClassName=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost:3306/firstproject?useUnicode=true&characterEncoding=UTF-8&profileSQL=false&autoSlowLog=false&slowQueryThresholdMillis=100&autoReconnect=true
datasource.username=us
etc..
并在 xml 上下文中添加这一行
<Environment name="spring.config.location" value="file:[path]\application.properties" type="java.lang.String"/>
在这里找到这个解决方案之前我一直在苦苦挣扎How to externalize application.properties in Tomcat webserver for Spring?
它会给你带来其他好处:
简单的弹簧配置 允许您使用嵌入式 tomcat 运行 webapp 如果您不小心将自己的 application.properties 打包到 war 文件中,生产 tomcat 将忽略它【讨论】:
【参考方案2】:我们遇到了同样的问题。我们将数据源声明为 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);
也许也可以。
【讨论】:
【参考方案3】:如果有人使用 applicationContext.xml 样式,我解决了这样的问题:
<bean id="myNamedExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="registrationPolicy" value="IGNORE_EXISTING" />
</bean>
【讨论】:
【参考方案4】:如果您想要使用注释的解决方案 Spring boot 已经定义了 MBeanExporter bean,所以你可以自动连接它
@Autowired
MBeanExporter mBeanExporter ;
然后更改注册策略
mBeanExporter.setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);
【讨论】:
【参考方案5】:我遇到了同样的错误,并通过将 registration="ignoreExisting" 添加到 mbean-export 部分来解决它:
<context:mbean-export server="mbeanServer" default-domain="mydomain" registration="ignoreExisting" />
【讨论】:
以上是关于迁移到 Tomcat 8:InstanceAlreadyExistsException 数据源的主要内容,如果未能解决你的问题,请参考以下文章
从 web.xml 迁移到基于 Java 的配置 - 无法启动 Tomcat 8
Tomcat 8 - LDAP:NameNotFoundException 错误代码 32,剩余名称为空字符串
Tomcat因项目迁移,启动窗口一闪而过,启动失败的解决办法。
在 Tomcat 6-Java 7/8 中运行 Tomcat 6-Java 6 WebApps