简体   繁体   中英

How to create custom c3p0 ComboPooledDataSource and refer in tomcat context.xml

I have a tomcat application server and my DB connection is defined in context.xml and fetched the data source as a 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>

rather than hardcoding the username and password here in context.xml.I want to store db credentials in aws secret manager and create the data source with retrieved DB credentials from aws secret manager.

to do this I created the following custom ComboPooledDataSource class.

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;
        }
    
    }

after that, i created a jar file from above implementation and put it in tomcat /lib folder.

and I did the following modifications in Context.xml file in tomcat/conf folder.

<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"/>

but when i start tomcat i am getting following exception.

thod failed; nested exception is org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'java:comp/env/datasource/test'; nested exception is javax.naming.NameNotFoundException: JNDI object with [java:comp/env/datasource/test] not found: JNDI implementation returned null at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFacto ry.java:199) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:400) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4770) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5236) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(Contain erBase.java:754) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:744) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:980) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1851) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

Caused by: javax.naming.NameNotFoundException: JNDI object with [java:comp/env/datasource/test] not found: JNDI implementation returned null at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:158) at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178) at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:96) at org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup.getDataSource(JndiDataSourceLookup.java:45)

I verified my DB credentials and DB configs are correct.

You are extending Tomcat JDBC 's ObjectFactory to create your datasource, which returns null whenever the type attribute is not javax.sql.DataSource , javax.sql.XADataSource or org.apache.tomcat.jdbc.pool.DataSource and logs the problem at a warning level (cf. source code ).

If you set type="javax.sql.DataSource" it should work, but your solution has a dependency on both Tomcat JDBC and C3P0.

I would rather retrieve username and password and call setUser and setPassword in the default constructor of CustomComboPoolDataSource and use the generic BeanFactory to configure it in Tomcat.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM