This deals with try/catch blocks and finallys. I always believed that "no matter what" a finally block is always called. While this seems to remain true, it does not seem to necessarily properly call the code within the block. In the section below I have some code and explanation of how a finally gets called, but does not execute the code within.
There seems to be an issue with closing a JDBC connection if a method returns in the middle of the try/catch block. It seems to call the finally, but does not close the connection. It does seem to call static methods like System.out.println() perfectly fine. I don't know if it being static has anything to do with it. I haven't researched it too far since it was really hard to find. First off you have to have a Factory like a ConnectionPool that spawns out inscances of an object for other classes to use. Then it must need to have the user close it's connection at some point so the Factory can control resources. The only example I really have on hand is a JDBC connection pool in a J2EE app server. This is where the problem occurd for us. If the methods "returns" are moved outside the try/catch block, the Connection.close() happens properly and the ConnectionPool does not complain. I realize the getColumnClose() is the better way to implement the code ayway, but I wanted to show everyone this problem in case they accidentally do it in their code somewhere. Any returns in the try or catches seemed to make the finally not be properly executed. I seem to remember some wierd rule about this at JavaOne last year, but my head is still racing from all that information. :-) Any comments? package test; import java.sql.*; import javax.sql.DataSource; import javax.naming.*; /** * <p>Title: TryCatchTest</p> * <p>Description: This is a test application for try/catch problem. If using * a Connection Pool in JDBC and you try to "return" a value within a try/catch * that is inside a method, the finally of that try/catch is not completely run. * It seems to go through the finally(I.E. Sytem.out.println() works, but the * Connection.close() is either never called or not executed. If the "return" * is moved to the outside of the catch block, the connection is properly closed. * <br> * We found this because a J2EE server which had a connection pool was telling * us we were not closing our connections. I dn't know if there is some rule that * when a "return" has been called only static methods or something like that can * be called.</p> * <p>Copyright: Copyright (c) 2002</p> * <p>Company: Western Electronics </p> * @author <a href="mail:[EMAIL PROTECTED]">Greg Davis</a> * @version 1.0 */ public class TryCatchTest { Context jndiContext; public TryCatchTest() { try { jndiContext = new InitialContext(); } catch(NamingException ne) {} } public String getColumnNoClose() { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql ="SELECT table_name FROM sequence"; conn =((DataSource)jndiContext.lookup("jdbc/mySourceDS")).getConnection(); ps = conn.prepareStatement(sql); rs = ps.executeQuery(); if(rs != null && rs.next()) { //This return causes the ?non-static? code within the finally to not to be run. return rs.getString("table_name"); } //same here, the finally ?non-static? code is not called. return null; } catch(NamingException ne) { //same here, the finally ?non-static? code is not called. return null; } catch(SQLException sqle) { sqle.printStackTrace(); //The same problem occurs here. The finally ?non-static? code is not called return null; } finally { //This system out works, but the conn.close() does not. The only way I //know how to check this is to create a ConnectionPool yourself that watches //the connections it spawns out, or user a pre-built one that does the same. //We use Orion 1.5.4 J2EE App server (free for development). if you want //to test this out. System.out.println("Finally called in noClose()"); try { if(rs != null) rs.close(); if(ps != null) ps.close(); if(conn != null) conn.close(); } catch(SQLException sqle) { sqle.printStackTrace(); } } } public String getColumnClose() { String returnValue = null; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { String sql ="SELECT table_name FROM sequence"; conn =((DataSource)jndiContext.lookup("jdbc/mySourceDS")).getConnection(); ps = conn.prepareStatement(sql); rs = ps.executeQuery(); if(rs != null && rs.next()) { //This does call the finally returnValue = rs.getString("table_name"); } } catch(NamingException ne) {} catch(SQLException sqle) { //This allso calles the finally if I break the quey sqle.printStackTrace(); } finally { //This one works normally System.out.println("Finally called in Close()"); try { if(rs != null) rs.close(); if(ps != null) ps.close(); if(conn != null) conn.close(); } catch(SQLException sqle) { sqle.printStackTrace(); } } return returnValue; } public static void main(String[] args) { TryCatchTest tct1 = new TryCatchTest(); System.out.println("tct1.getColumnNoClose():" + tct1.getColumnNoClose()); System.out.println("tct1.getColumnClose():" +tct1.getColumnClose()); } }