How to extend c3p0 ComboPooledDataSource

Good. I have a resource in Tomcat 5.5 in server.xml to connect to the database as follows:

<Resource name="jdbc/MyApp" auth="Container" type="com.mchange.v2.c3p0.ComboPooledDataSource" driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" maxPoolSize="100" minPoolSize="5" acquireIncrement="5" user="username" password="password" factory="org.apache.naming.factory.BeanFactory" jdbcUrl="jdbc:sqlserver://localhost:1433;databaseName=myDatabase;autoReconnect=true" /> 

Has anyone tried to extend the above ComboPooledDataSource? The problem is that the database password has clear text. The idea is to first encrypt the password and put the encrypted key in server.xml. I have a decryption, so I can decrypt the key before trying to connect to the database.

I found an example solution for my problem for org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory, but I do not use this connection pool. I am using C3P0. Has anyone tried this before with C3P0?

+4
source share
4 answers

Yes, you cannot extend com.mchange.v2.c3p0.ComboPooledDataSource because it is publicly available. Here is a workaround by which I have achieved this.

I extended org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy and passed the data source com.mchange.v2.c3p0.ComboPooledDataSource as a constructor argument.

Here is my hibernate.cfg.xml configuration of the overlying data source:

 <bean id="dataSource" class="MyDataSource"> <constructor-arg ref="c3p0DataSource" /> </bean> <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver.className}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="acquireIncrement" value="${dataSource.acquireIncrement}" /> <property name="acquireRetryAttempts" value="${dataSource.acquireRetryAttempts}" /> <property name="acquireRetryDelay" value="${dataSource.acquireRetryDelay}" /> <property name="autoCommitOnClose" value="${dataSource.autoCommitOnClose}" /> <property name="breakAfterAcquireFailure" value="${dataSource.breakAfterAcquireFailure}" /> <property name="checkoutTimeout" value="${dataSource.checkoutTimeout}" /> <property name="debugUnreturnedConnectionStackTraces" value="${dataSource.debugUnreturnedConnectionStackTraces}" /> <property name="forceIgnoreUnresolvedTransactions" value="${dataSource.forceIgnoreUnresolvedTransactions}" /> <property name="idleConnectionTestPeriod" value="${dataSource.idleConnectionTestPeriod}" /> <property name="initialPoolSize" value="${dataSource.initialPoolSize}" /> <property name="maxAdministrativeTaskTime" value="${dataSource.maxAdministrativeTaskTime}" /> <property name="maxConnectionAge" value="${dataSource.maxConnectionAge}" /> <property name="maxIdleTime" value="${dataSource.maxIdleTime}" /> <property name="maxIdleTimeExcessConnections" value="${dataSource.maxIdleTimeExcessConnections}" /> <property name="maxPoolSize" value="${dataSource.maxPoolSize}" /> <property name="maxStatements" value="${dataSource.maxStatements}" /> <property name="maxStatementsPerConnection" value="${dataSource.maxStatementsPerConnection}" /> <property name="minPoolSize" value="${dataSource.minPoolSize}" /> <property name="numHelperThreads" value="${dataSource.numHelperThreads}" /> <property name="propertyCycle" value="${dataSource.propertyCycle}" /> <property name="testConnectionOnCheckin" value="${dataSource.testConnectionOnCheckin}" /> <property name="testConnectionOnCheckout" value="${dataSource.testConnectionOnCheckout}" /> <property name="unreturnedConnectionTimeout" value="${dataSource.unreturnedConnectionTimeout}" /> </bean> Mine jdbc.properties file: jdbc.driver.className=com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc.url=xxxxx jdbc.username=xxx jdbc.password=xxxxxxxxx #Encrytped password here jdbc.hibernate.dialect=org.hibernate.dialect.SQLServerDialect hibernate.show_sql=false hibernate.hbm2ddl.auto=update dataSource.acquireIncrement=3 dataSource.acquireRetryAttempts=30 dataSource.acquireRetryDelay=60000 dataSource.autoCommitOnClose=false dataSource.breakAfterAcquireFailure=false dataSource.checkoutTimeout=0 dataSource.debugUnreturnedConnectionStackTraces=false dataSource.forceIgnoreUnresolvedTransactions=false dataSource.idleConnectionTestPeriod=0 dataSource.initialPoolSize=10 dataSource.maxAdministrativeTaskTime=0 dataSource.maxConnectionAge=0 dataSource.maxIdleTime=0 dataSource.maxIdleTimeExcessConnections=0 dataSource.maxPoolSize=10 dataSource.maxStatements=0 dataSource.maxStatementsPerConnection=0 dataSource.minPoolSize=10 dataSource.numHelperThreads=3 dataSource.propertyCycle=0 dataSource.testConnectionOnCheckin=false dataSource.testConnectionOnCheckout=false dataSource.unreturnedConnectionTimeout=0 Mine extended class where I decrypt the password before passing the datasource to transaction Proxy wrapper. import javax.sql.DataSource; import org.jasypt.util.text.BasicTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; import com.csc.emms.common.EMMSConstraints; import com.mchange.v2.c3p0.ComboPooledDataSource; public class MyDataSource extends TransactionAwareDataSourceProxy { private static char[] appName = { 'B', 'I', 'N', 'G', 'O', 'D', 'I', 'N', 'G', 'O' }; @Autowired // Inject your class by constructor MyDataSource(ComboPooledDataSource dataSource) { super.setTargetDataSource(decryptPassword(dataSource)); } private DataSource decryptPassword(ComboPooledDataSource dataSource) { dataSource.setPassword(decode(dataSource.getPassword())); return dataSource; } private String decode(String encodedPassword) { BasicTextEncryptor decoder = new BasicTextEncryptor(); decoder.setPasswordCharArray(appName); return decoder.decrypt(encodedPassword); } private String encode(String password) { BasicTextEncryptor encoder = new BasicTextEncryptor(); encoder.setPasswordCharArray(appName); return encoder.encrypt(password); } } Hope this resolved your issue. 
+1
source

you can use jasypt to encrypt the properties file and then use the encrypted properties in the bean data source.

jasypt also supports spring, and it is very easy to use. read this for more details.

0
source

Since com.mchange.v2.c3p0.ComboPooledDataSource public final , you cannot extend it. I am also working on a workaround. This thread will be updated after execution.

0
source

You cannot extend ComboPooledDataSource , but you can basically duplicate it by extending its parent class AbstractComboPooledDataSource . You can really get close to duplication, either by getting the source from Github , or by decompiling the class file. The result will look something like this:

 import com.mchange.v2.c3p0.AbstractComboPooledDataSource; public final class YourC3p0DataSource extends AbstractComboPooledDataSource implements Serializable, Referenceable { public void setPassword(String encryptedPassword) { try { String decryptedPassword = yourDecryption(encryptedPassword); super.setPassword(decryptedPassword); } catch (Exception e) { /* ... */ } } /* Increment a few other methods found in ComboPooledDataSource. */ } 
0
source

All Articles