Home arrow static arrow Java Programming [Archive] - Catching causal exceptions from finally{} block?
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - Catching causal exceptions from finally{} block?
This topic has 84 replies on 6 pages.    « Previous | 1 | 2 | 3 | 4 | 5 | 6 | Next »

Posts:27,518
Registered: 11/3/97
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 5:18 PM (reply 15 of 84)



 
I didn't think one could obtain a reference to that
original Exception. Thanks,

No I didn't write the code, but in my bytecode
evaluation it's evident that finally{} does a throw.
This is due to the good-ol' problem of cleaning up
java.sql.Connection objects to a connection pool in
the finally block yet wanting to ensure the original
exception is propagated to the calling method,
whereas the OP should catch the exception,
maintain temporary reference, then use it as a
reference to the other Exception in the finally
if there's no better way for her to do it.

I doubt this is a good idea.

You are going to encounter one of the following....
1. No exception at all.
2. Exception only in the try block.
3. Exception in both places.
3. Exception only in the finally block (due to a close)

Analysis of each case.
1. Obviously this doesn't matter.
2. Obviously the exception should be returned to the caller.
3. In all likelyhood the either the first exception caused the second one or both operations failed for the same external reason. And the caller probably doesn't actually care that the second (finally case) failed, all they care about is that the first one didn't.
4. Something succeeded in the try block. By throwing the exception in the finally block you obscure that fact from the user. Consider this example the user inserts a row successfully, while closing the database connection it fails because the database has now gone down. The caller is going to react as though the insert failed. But it didn't. Is that the behavior that you want the caller to see?
 

Posts:426
Registered: 11/1/00
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 9:54 PM (reply 16 of 84)



 
Quote on the code:
    finally {        // close ResultSet, Statement, Connection        // NO EXCEPTION re-throwing    }


Actually, this is where they are getting into trouble. There may be an SQLException in the try{} block, but here in finally the DB has died (in this case) and the close() (oddly) on the PreparedStatement throws an SQLException also, thus I'm getting the closure exception, NOT the original exception stating why a query may have failed in the first place (albeit most likely the same cause as the closure). As by contract the close() on either of those throws SQLException, they must be handled independently within the context of that method, no?
 

Posts:2,830
Registered: 9/1/03
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 10:02 PM (reply 17 of 84)



 
you know, jverd, that if checked exceptions had not been put on
the sql calls here, we may find that there would be no try block
altogether and hence no finally block so infact this persons error
would not be occuring and the problem would probably be solved!

jensenje
As by contract the close() on either of those throws SQLException,
they must be handled independently within the context of that method, no?

Not sure what your question is ... you must smother (or log) the 'close()'
exception that occurs in the 'finally' part. If you do not throw an exception
from finally, and an exception occurs in 'try' the exception will not get lost.

Is that your question?
 

Posts:426
Registered: 11/1/00
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 10:07 PM (reply 18 of 84)



 
Correct, generally one should catch and ignore or log an exception of a throwable method that must be executed in finally{}. Just was clarifying where my issues are in this code maintenance I'm doing is that in general all java.sql.[(Prepared)Statement|ResultSet|Connection].close() methods are not being handled at all! :-(
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 7:50 AM (reply 19 of 84)



 
Quote on the code:
finally {// close ResultSet, Statement, Connection// NO EXCEPTION re-throwing}


Actually, this is where they are getting into trouble.
There may be an SQLException in the try{} block, but
here in finally the DB has died (in this case) and
the close() (oddly) on the PreparedStatement throws
an SQLException also, thus I'm getting the closure
exception, NOT the original exception stating why a
query may have failed in the first place (albeit most
likely the same cause as the closure). As by
contract the close() on either of those throws
SQLException, they must be handled independently
within the context of that method, no?

In this case, finally should be something like
finally {    try {        rsltSet.close();        stmt.close();        con.close();    }    catch (Throwable th) {        logger_.log("Error closing db", th);    }} 

As I was trying to say, and as jschell explained more clearly, you don't want what happens in finally to change how the method completes. If there's a problem, by all means log it, but don't let finally throw or return.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 7:54 AM (reply 20 of 84)



 
you know, jverd, that if checked exceptions had not
been put on
the sql calls here, we may find that there would be no
try block
altogether and hence no finally block so infact this
persons error
would not be occuring and the problem would probably
be solved!

Huh? That doesn't solve the problem, that just hides it. Checked exceptions or no, you don't want cleanup to change how your method completes. If all exceptions were unchecked, you could successfully insert or retrieve from the DB, then close could throw an unchecked exception, and the whole method would then throw the exception, even though it did its work successfully.

And even if there were no unchecked exceptions, if the person read the docs, (following your logic from the other thread :-) ), they'd see that an unchecked SQLException could be thrown and they'd create the same try/finally structure anyway.
 

Posts:13,769
Registered: 00-11-29
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:04 AM (reply 21 of 84)



 
Let's step back. I'm guessing the OP is looking at code like this:
public void method() throws SQLException{    try {        // SQL code that could throw an exception    } finally {        connection.close(); // or something    }}


Since the method is declared to throw SQLException there is no requirement to wrap the exception in finally. This is a common error and it causes the worst kind of bug (IMO.) The bug that hapens so infrequently that it never shows up in testing but every once in while happens in production wasting everyone's time trying to figure out whether it's really a problem that Oracle thinks it's an error when you close a connection that's already closed.
 

Posts:19,725
Registered: 9/26/01
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:24 AM (reply 22 of 84)



 
The bug that hapens so
infrequently that it never shows up in testing but
every once in while happens in production wasting
everyone's time trying to figure out whether it's
really a problem that Oracle thinks it's an error when
you close a connection that's already closed.

The contract of Connection.close() states that calling it on a connection which is already closed is a no-op. I see no problem with letting the possible SQLException thrown by close() be the exception returned, because if it does in fact throw an exception, something's "really wrong" with the database.
 

Posts:1,577
Registered: 00-02-25
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:29 AM (reply 23 of 84)



 
public void foobar() throws BarException, FooException{try {throw new FooException();} finally {throw new BarException();}}

I've skipped a bunch of responses, so this may already have been suggested ... going along with the commandment that "thou shalt not knowlingly throw from finally," this code could be rewritten like this:
try {    throw new FooException();}catch (Exception e) {    throw new BarException(e);    // assuming BarException can wrap something else}finally {    // do any real cleanup here ... or get rid of it if not needed}
 

Posts:27,518
Registered: 11/3/97
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:31 AM (reply 24 of 84)



 

In this case, finally should be something like

finally {
try {
rsltSet.close();
stmt.close();
con.close();
}
catch (Throwable th) {
logger_.log("Error closing db", th);
}
}

Actually you need a try/catch around each of the close methods.
 

Posts:19,725
Registered: 9/26/01
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:33 AM (reply 25 of 84)



 

In this case, finally should be something like

finally {
try {
rsltSet.close();
stmt.close();
con.close();
}
catch (Throwable th) {
logger_.log("Error closing db", th);
}
}

Actually you need a try/catch around each of the close
methods.


I could argue that you don't, because if for example rsltSet.close() throws an exception - guess what? stmt.close() is probably going to as well, so the intended "proper cleanup" ain't gonna happen anyway.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:38 AM (reply 26 of 84)



 
Let's step back. I'm guessing the OP is looking at
code like this:
public void method() throws SQLException{try {// SQL code that could throw an exception} finally {connection.close(); // or something}}


Since the method is declared to throw SQLException
there is no requirement to wrap the exception in
finally.

Not to get it to compile, no. But to get correct behavior, you must put a try/catch inside finally.

This is a common error and it causes the
worst kind of bug (IMO.) The bug that hapens so
infrequently that it never shows up in testing but
every once in while happens in production wasting
everyone's time trying to figure out whether it's
really a problem that Oracle thinks it's an error when
you close a connection that's already closed.

That's why you log, don't smother. If you're lucky, the exception's message will tell you "already closed." If not, you've got some work ahead of you, but at least your code is behaving properly.

Again, the principle here is to not let cleanup change the results of the real processing.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:39 AM (reply 27 of 84)



 
I've skipped a bunch of responses, so this may already
have been suggested ... going along with the
commandment that "thou shalt not knowlingly throw from
finally," this code could be rewritten like this:
try {throw new FooException();}catch (Exception e) {throw new BarException(e);    // assuming BarExceptioncan wrap something else}finally {// do any real cleanup here ... or get rid of it ifnot needed}

Yep. That's kind of what I was suggesting in some sample code several posts back.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:41 AM (reply 28 of 84)



 
Actually you need a try/catch around each of the close
methods.

Yeah, I know. I was shortcutting it for clarity's sake, but I figured I'd regret it. In real life, I have a helper class that does the try/catch/log for closing DB stuff, files, sockets, etc. Keeps the finally blocks cleaner.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 3, 2004 8:43 AM (reply 29 of 84)



 
I could argue that you don't, because if for example
rsltSet.close() throws an exception - guess what?
stmt.close() is probably going to as well, so the
intended "proper cleanup" ain't gonna happen anyway.

I was sort of thinking the same thing when I opted to shortcut it, but then, I realized I couldn't be sure enough of that to really justify the position. Each one really should have its own try/catch. I would think that probably one of them throwing an exception would indicate you're not going to get proper cleanup from the others, but it's so simple to apply due diligence here.
 
This topic has 84 replies on 6 pages.    « Previous | 1 | 2 | 3 | 4 | 5 | 6 | Next »