I personally follow the old school of thought, 1 entry, 1 exit...while this
was probably intended to describe the entry/exit points of a program itself,
I use this same idea when coding...rather then returning in the middle of a
block of code, I generally try and return at the end, while this can
sometimes increase the complexity of the code, it generally makes it easier
to read and follow...
However, I think you problem relates more to what's going on in the final
block then anywhere else...each close statement should be trapped in their
own try/catch block (as mentioned before), while this increases the amount
of code, it ensures that each statement can be called...
Shane
-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED]]On Behalf Of Scott Farquhar
Sent: Wednesday, 10 April 2002 08:16 am
To: Orion-Interest
Subject: Re: JDBC try/catch Pitfall ***MUST READ***
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.*;
>
> /**
> * Title: TryCatchTest
> * 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.
> *
> * 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.
> * Copyright: Copyright (c) 2002
> * Company: Western Electronics
> * @author Greg Davis
> * @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