如何创建自定义c3p0 combopooleddatasource并在tomcat context.xml中引用

ny6fqffe  于 2021-08-25  发布在  Java
关注(0)|答案(1)|浏览(325)

我有一个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)
我验证了我的数据库凭据和数据库配置是否正确。

jobtbby3

jobtbby31#

您正在扩展tomcat jdbc的 ObjectFactory 创建数据源,返回 null 无论何时类型属性不可用 javax.sql.DataSource , javax.sql.XADataSourceorg.apache.tomcat.jdbc.pool.DataSource 并以警告级别记录问题(参见源代码)。
如果你设定 type="javax.sql.DataSource" 它应该可以工作,但是您的解决方案同时依赖于TomcatJDBC和c3p0。
我宁愿检索用户名和密码并拨打电话 setUsersetPassword 在的默认构造函数中 CustomComboPoolDataSource 并使用通用的 BeanFactory 在tomcat中配置它。

相关问题