Skip to main content

Patch Leaky Connections with AOP

Posted by crazybob on March 5, 2004 at 1:23 PM PST

In a recent thread on TheServerSide.com, readers voiced concern over JDBC drivers and connection pools that fail to close Statements and ResultSets when you call Connection.close(). If an application uses such a broken driver or pool and doesn't explicitly close these objects, the application will slowly leak resources and crash.

Erring on the side of caution, many developers write JDBC code like the following example or rely on frameworks to create and close their ResultSets for them:

  Connection c = ...;
  Statement s = null;
  ResultSet rs = null;
  try {
    // some JDBC code...
  }
  finally {
    if (rs != null) {
      try {
        rs.close();
      }
      catch (Exception e) {}
    }
    if (s != null) {
      try {
        s.close();
      }
      catch (Exception e) {}
    }
    try {
      c.close();
    }
    catch (Exception e) {}
  }

Rather than repeating the same code over and over again or limiting yourself to one ResultSet at a time, I suggest a proxy-based design: wrap the Connection, track the child resources and close them when the user calls Connection.close() per spec. After discovering that my own connection pool waits until the next time it gives out a connection before cleaning up its resources, I decided this would be a perfect opportunity to apply dynaop.

The resulting proof of concept reuses code in ways its OO counterpart could only dream of. In my design, Connections contain Statements which in turn contain ResultSets. I turn the Connections and Statements into containers and add their respective children using generic container advice. Additional advice applied to the close() methods works with the container advice and closes ResultSets before Statements and Statements before Connections. A last piece of advice wraps Statement instances and applies the container and close advice. We can now shave some lines off of our previous example in good conscience:

  Connection c = LeakyConnection.wrap(...);
  try {
    // some JDBC code...
  }
  finally {
    try {
      // this automatically cleans up resources.
      c.close();
    }
    catch (Exception e) {}
  }
Related Topics >>