Solve DB Connection Problems once for ALL
One of the most important problems a database driven application faces is to manage its connections to the database.
Typically these applications use connection pooling. The advantages of pooling are many, connections can be reused , so there is no lag time in serving the connection requested.
But along with this powerful advantage , it becomes critically important that the connection after it has been used , be returned to the pool promptly.
In this article I will be concentrating on how Weblogic manages the DB pools.
A look under the hood:
I was curious to know how a connection pool gets implemented. Especially of interest is how the connection would be returned to the pool , once the connection has been used.
So I decompiled Oracle Java classes “Classes12.zip”.
A closer look at the Connection class shows that , it implements a listener, and hence every time the connection is closed, the listeners are notified, that the connection is closed.
Now in the ideal world for every open connection, there will be a close connection.
And also, in your projects, you make sure that you always have a try-catch-finally block, and close the connections properly. But sometimes, you do not have a choice, and you inherit a code pile from someone. Considering the amount of postings on the internet about conection leaks, it is a common problem. Further you might suspect that there might be some connection leaks lurking in the code somewhere.
Here is a way to solve the problem:
I hope that you have a central object, which handles all the database access and return of connections. Lets call this object DBMSConnection. The DBMSConnection object has two methods , getConnection and safeClose. As the method names suggest, getConnection , with all the internal DB specific plumbing allows you to make a connection from the pool, and safeClose is used to return the connection back to the pool.
public Connection getConnection() throws SQLException {
Connection con = null;
System.out.println("Inside getConnection");
StackTraceElement stke = new Exception().getStackTrace()[1];
String callMethod = stke.getClassName() + "." + stke.getMethodName();
System.out.println("Calling Method: " + callMethod);
return con;
}
/** closes a resultset, a statement and connection in the right order, and
* only if they are not null.
*/
public static synchronized void safeClose (ResultSet resultSet, Statement stmt, Connection connection) throws SQLException {
System.out.println("Inside safeClose");
StackTraceElement stke = new Exception().getStackTrace()[1];
String callMethod = stke.getClassName() + "." + stke.getMethodName();
}
public static void logInTable(boolean insert,String methodName,int hashCode)
throws Exception
{
Connection con=null;
Statement stmt = null;
try
{
con = new DBMSConnection().getConnection();
stmt = con.createStatement();
if (insert)
{
stmt.executeUpdate("INSERT INTO TestConnRelease " +
" VALUES( connectionid_seq.nextval,sysdate,NULL,'" + methodName
+ "','Y',NULL," + hashCode);
}else
{
stmt.executeUpdate("UPDATE TestConnRelease " +
" SET conRel='Y',RelDate=sysdate where " +
"callingMethodName='" + methodName +"' AND hashCode=" + hashCode);
}
}catch(Exception e)
{
e.printStackTrace();
}finally
{
safeClose(null,stmt,con);
}
}