How to stop the c3p0 connection pool from hiding the cause of connection exceptions?

I have an application that uses c3p0 to pool pools. When there is any problem connecting to the database, I get an exception like this:

java.sql.SQLException: An SQLException was provoked by the following failure: com.mchange.v2.resourcepool.ResourcePoolException: A ResourcePool cannot acquire a new resource -- the factory or source appears to be down. at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106) at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65) at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:531) at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) at com.pontiflex.monitor.dao.ConnectionManager.getConfigReadOnlyDbConnection(Unknown Source) at com.pontiflex.monitor.dao.MonitorServiceDAO.getLiveIOCountForOrganization(Unknown Source) at com.pontiflex.monitor.BillingMonitor.getComparisonValueForActivation(Unknown Source) at com.pontiflex.monitor.AbstractMonitor.isMonitoringActive(Unknown Source) at com.pontiflex.monitor.AbstractMonitor.generateAlerts(Unknown Source) at com.pontiflex.monitor.AbstractMonitor.doMonitoring(Unknown Source) at com.pontiflex.monitor.worker.MonitorWorker.run(Unknown Source) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.lang.Thread.run(Thread.java:662) Caused by: com.mchange.v2.resourcepool.ResourcePoolException: A ResourcePool cannot acquire a new resource -- the factory or source appears to be down. at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1279) at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557) at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) ... 14 more 

The same exception will occur regardless of what the problem is: whether there are problems with the network connection, problems with the server (too many connections), or problems with the configuration. If I turn on debug logging for the mysql jdbc and c3p0 drivers, I will get additional information:

 WARN com.mchange.v2.resourcepool.BasicResourcePool com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@4e0747 84 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception: com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections" at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:921) at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1070) at com.mysql.jdbc.Connection.createNewIO(Connection.java:2775) at com.mysql.jdbc.Connection.<init>(Connection.java:1555) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285) at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135) at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182) at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137) at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014) at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32) at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810) at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) 

Is there anything I can do to get c3p0 to give me the main reason when it throws a ResourcePoolException without setting the log configuration?

+4
source share
1 answer

SQLException is the (noted) exception that JDBC apis are allowed to throw, so c3p0 should "wrap" the underlying Exceptions that did not eat SQLExceptions in the usual way. Calling getCause () for these Exceptions will provide the original Throwable if you want to check for something specific.

In the specific example that you are quoting, something else happens. The problem is that the Thread that throws the Exception is not your client thread. c3p0-internal threads acquire connections from the database. Your client threads acquire connections from the pool. These two actions are disengaged, since c3p0 can control - that's all that is connected with the Connection pool. First, internal threads perform a β€œround” of acquisition attempts (by default, 30 attempts with a delay of 1 second between them, but you can reconfigure if you want).

If ALL attempts to bypass the connection fail, the internal threads c3p0 ...

1) Record the failure and the last exception seen when trying. This is the second exception you are quoting. Please note that this is registered in WARNING and not at the DEBUG level. If you have c3p0 registered in INFO - what you need - you will see these messages. [If you want to see each individual Exception, all 30 Exceptions that must occur (under hyphens) before declaring a waiver, you need to enable registration in DEBUG (or FINE or ALL).]

2) After the log failed, c3p0 will abort wait () clients and throw a ResourcePoolException, which becomes a SQLException. This is the first exception you are quoting. A ResourcePoolException error is reported.

3) if breakAfterAcquireFailure is set to false (the default), the pool will recover after the acquisition fails. He will try to acquire new connections again when new clients appear. If breakAfterAcquireFailure is true, the pool will always respond to new client requests using Exception.

In any case, I hope this is not entirely useless. c3p0 can detect a custom exception type that will cause a wrapped exception to be delivered to clients, so clients can check for a failure in the code, but at least for now this is not the case. (Unfortunately!)

+4
source

All Articles