There is a database connection leak in one of our legacy application, and I tracked it down to this little gem. From debugging, I can see the same logical connection being returned for multiple threads (not good!). But I'm struggling to understand why that is happening.
We are using the ojdbc6 driver, setup on a WebLogic Data Source with connection pooling.
Code that produces problem
public class MyDummyDaoUtil {
//note: this is a public field in a singleton (not a static field though...)
public Connection conn;
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
//the same logical connection is produced by the data source or something else happening?
conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
Updated fix
public class MyDummyDaoUtil {
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
Connection conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
Summary of fix
- Incorrect lazy initialization of the instance
- Connection should be a local variable in the method, not the singleton class