我有一个tomcat应用服务器,我的db连接在context.xml中定义,并作为jndi获取数据源。
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Resource name="datasource/test" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
factory="org.apache.naming.factory.BeanFactory"
user="abc"
password="abc123"
jdbcUrl="jdbc:mysql://localhost:3306/jacplus"
driverClass="com.mysql.jdbc.Driver"
minPoolSize="2"
initialPoolSize="30"
maxPoolSize="50"
idleConnectionTestPeriod="600"
acquireRetryAttempts="30"/>
</Context>
我不想在context.xml中硬编码用户名和密码,而是想在aws secret manager中存储db凭据,并使用从aws secret manager检索到的db凭据创建数据源。
为此,我创建了以下自定义combopooleddatasource类。
import com.mchange.v2.c3p0.AbstractComboPooledDataSource;
import javax.naming.Referenceable;
import java.io.Serializable;
public final class CustomComboPoolDataSource extends AbstractComboPooledDataSource implements Serializable, Referenceable {
}
import com.mchange.v2.c3p0.PoolConfig;
import org.apache.tomcat.jdbc.pool.DataSourceFactory;
import java.sql.SQLException;
import java.util.Properties;
import javax.naming.Context;
import javax.sql.DataSource;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
public class SecureTomcatDataSourceImpl extends DataSourceFactory {
public SecureTomcatDataSourceImpl() {
}
@Override
public DataSource createDataSource(Properties properties, Context context, boolean XA) throws SQLException {
String userName = getFromAWSSecretManager("username");
String password = getFromAWSSecretManager("password");
PoolConfiguration poolProperties = SecureTomcatDataSourceImpl.parsePoolProperties(properties);
PoolConfig poolConfig = new PoolConfig(properties);
CustomComboPoolDataSource customDataSource = new CustomComboPoolDataSource();
customDataSource.setProperties(properties);
customDataSource.setUser(userName );
customDataSource.setPassword(password);
// The rest of the code is copied from Tomcat's DataSourceFactory.
if (poolProperties.getDataSourceJNDI() != null && poolProperties.getDataSource() == null) {
performJNDILookup(context, poolProperties);
}
return customDataSource;
}
}
之后,我根据上面的实现创建了一个jar文件,并将其放在tomcat/lib文件夹中。
我在tomcat/conf文件夹的context.xml文件中做了以下修改。
<Resource name="datasource/test" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
**factory="com.aws.rds.SecureTomcatDataSourceImpl"
user=""
password=""**
jdbcUrl="jdbc:mysql://localhost:3306/jacplus"
driverClass="com.mysql.jdbc.Driver"
minPoolSize="2"
initialPoolSize="30"
maxPoolSize="50"
idleConnectionTestPeriod="600"
acquireRetryAttempts="30"/>
但当我启动tomcat时,我遇到了以下异常。
thod失败;嵌套异常为org.springframework.jdbc.datasource.lookup.datasourcelookupfailureexception:未能查找名为“java:comp/env/datasource/test”的jndi数据源;嵌套异常为javax.naming.namenotfoundexception:jndi对象,未找到[java:comp/env/datasource/test]:jndi实现在org.springframework.beans.factory.support.abstractautowirecapablebeanfactory.initializebean(abstractautowirecapablebeanfactory.java:1745)处返回nullorg.springframework.beans.factory.support.abstractautowirecapablebeanfactory.docreatebean(abstractautowirecapablebeanfactory.java:576)位于org.springframework.beans.factory.support.abstractautowirecapablebeanfactory.createbean(abstractautowirecapablebeanfactory.java:498)位于org.springframework.beans.factory.support.abstractbeanfactory.lambda$dogetbean$0(abstractbeanfactory.java:320)位于org.springframework.beans.factory.support.defaultsingletonbeanregistry.getsingleton(defaultsingletonbeanregistry.java:222)位于org.springframework.beans.factory.support.abstractbeanfactory.dogetbean(abstractbeanfactory.java:318)位于org.springframework.beans.factory.support.abstractbeanfactory.getbean(abstractbeanfactory.java:199)位于org.springframework.context.support.abstractapplicationcontext.getbean(abstractapplicationcontext.java:1083)位于org.springframework.context.support.abstractapplicationcontext.finishbeanfactoryinitialization(abstractapplicationcontext.java:853)位于org.springframework.context.support.abstractapplicationcontext.refresh(abstractapplicationcontext.java:546)位于org.springframework.web.context.contextloader.configureandrefreshwebapplicationcontext(contextloader.java:400)位于org.springframework.web.context.contextloader.initwebapplicationcontext(contextloader.java:291)org.springframework.web.context.contextloaderlistener.contextinitialized(contextloaderlistener.java:103)在org.apache.catalina.core.standardcontext.listenerstart(standardcontext.java:4770)在org.apache.catalina.util.lifecyclebase.start(lifecyclebase.java:150)在org.apache.catalina.core.containerbase.addchildinternal(containerbase.java:754)在org.apache.catalina.core.containerbase.addchild(containerbase.java:730)在org.apache.catalina.core.standardhost.addchild(standardhost.java:744)在org.apache.catalina.startup.hostconfig.deploywar(hostconfig.java:980)在org.apache.catalina.startup.hostconfig$deploywar.run(hostconfig.java:1851)在java.util.concurrent.executors$runnableadter.call(executors.java:511)在java.util.concurrent.futuretask.run(futuretask.java:266)在java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1149)在java.lang.thread.run(thread.java:748)处的java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:624)
原因:javax.naming.namenotfoundexception:jndi对象[java:comp/env/datasource/test]未找到:jndi实现在org.springframework.jndi.jndemplate.lookup(jndemplate.java:158)在org.springframework.jndemplate.lookup(jndemplate.java:178)处返回nullorg.springframework.jndi.jndilocatorsupport.lookup(jndilocatorsupport.java:96)位于org.springframework.jdbc.datasource.lookup.jndiadatasourcelookup.getdatasource(jndiadatasourcelookup.java:45)
我验证了我的数据库凭据和数据库配置是否正确。
1条答案
按热度按时间jobtbby31#
您正在扩展tomcat jdbc的
ObjectFactory
创建数据源,返回null
无论何时类型属性不可用javax.sql.DataSource
,javax.sql.XADataSource
或org.apache.tomcat.jdbc.pool.DataSource
并以警告级别记录问题(参见源代码)。如果你设定
type="javax.sql.DataSource"
它应该可以工作,但是您的解决方案同时依赖于TomcatJDBC和c3p0。我宁愿检索用户名和密码并拨打电话
setUser
及setPassword
在的默认构造函数中CustomComboPoolDataSource
并使用通用的BeanFactory
在tomcat中配置它。