This site demonstrates the pitfalls with using returns & finally: http://www.cs.arizona.edu/sumatra/hallofshame/
It seems like this behaviour is not specified by the Java Language Specification. Cheers, Scott Greg Davis wrote: > 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()); > } > } > > -- Scott Farquhar :: [EMAIL PROTECTED] Atlassian :: http://www.atlassian.com Supporting YOUR J2EE World