I’ve been going at this for many many hours without success. I’m instantiating a DataSource in a multi threaded application. All threads get connections from the DataSource and close them in finally blocks (I’ve gone line by line to make sure that connections are released). The problem I’m having is that even though the close method is called on every connection theyr not being released by the DataSource. I know this because I have a different thread that prints the source.getNumActive() from the DBCP data source.
This is the basic setup.
public class DataSourceHolder {
private static DataSource source;
static {
get the data source either from jndi or created from scratch
}
public DataSource getDataSource() { return source; }
}
I have a simple JdbcPattern (like springs JdbcTemplate but extremely simple) to encapsulate all boilerplate code. This is defined something like so:
public class JdbcPattern {
private DataSource source;
public JdbcPattern(DataSource source) {
this.source = source;
}
public int executeMethods(....) {
Connection c = source.getConnection();
try {
.. do the statements
} finally {
try { c.close(); } catch (SQLException ignore) { }
}
}
public List<?> queryMethods(....) {
}
}
Finally I have four threads that get started at the beginning of the program. This threads sleep for a while and on wakeup instantiate a JdbcPattern with the DataSourceHolder provider DataSource and start doing stuff. The stuff gets done and when the connections is closed, it is not really released by the DataSource. After the DataSource max connections the program freezes due to no more connections can be instantiated.
How would you go about diagnosing this?
EDIT. This is running on tomcat. All the common methods are being loaded by catalina common loader and the threads are run inside one of the web applications. I’ve been thinking it might be a class loader problem.
You shouldn’t ignore a failure to close. Wrap it in an unchecked exception or log it, but don’t ignore. If there was some odd error when trying to release the connection to the pool, you won’t know.
I would recommend creating your own wrapper for the pool DataSource. You can log calls to getConnection along with a stack trace and a unique identifier of the connection. Also log the same way in your JdbcPattern when it calls close. Find the identifiers of the connections that are not closed, note where they are taken out of the pool from the getConnection stack trace. You could also make your DataSource wrapper do this analysis inside the server, but that is more code and more chance for error. I would try with simple logging first. Consider leaving this logging in the product, but below the normal logging theshold. You will need it again.