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.    1 | 2 | 3 | 4 | 5 | 6 | Next »

Posts:426
Registered: 11/1/00
Catching causal exceptions from finally{} block?  
Aug 2, 2004 2:50 PM



 
I have some code that I have not developed, yet from what I can tell throws Exceptions as in the following psuedo-code:

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


This expectedly returns BarException, not FooException. Question is since FooException was thrown, is there any way to get a reference to the original cause?
 

Posts:19,725
Registered: 9/26/01
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 2:56 PM (reply 1 of 84)



 
You're in control of what the code does, so you keep track of which exception you want it to "finally" end up throwing.
FooException thrown = null;
...
catch (FooException e) {
thrown = e;
}
...
finally {
if (thrown == null) {
// do some other logic which may throw BarException
}
else {
// do some logic, and maybe rethrow thrown here
}
}
 

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



 
This expectedly returns BarException, not
FooException. Question is since FooException was
thrown, is there any way to get a reference to the
original cause?

No. Only one exception is thrown at a time. Doing this kicks the original expception to the curb.

However, If it does this,
throw new BarException(e);
then you can get the cause from barexception.
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:17 PM (reply 3 of 84)



 
I would advise against throwing any exceptions from finally. You also should not return from finally.

Finally is there to clean up on the way out of the try statement, regardless of how the try block completed. You don't want that cleanup interfering with the try statement completing normally or throwing whatever exception it's throwing. Any time I do anything inside finally that could throw an exception, I always catch Exception or Throwable inside finally.
 

Posts:13,769
Registered: 00-11-29
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:22 PM (reply 4 of 84)



 
Any time I do anything inside
finally that could throw an exception, I always catch
Exception or Throwable inside finally.

The OP is looking at someone else's code and trying to figure out whether it is valid.

I would also add to your statement that in the extremely rare case that an Exception thrown from finally needs to be reported, I think wrapping the original is acceptable.
 

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



 
The OP is looking at someone else's code and trying to
figure out whether it is valid.

Aaaahh. Missed that part.

@OP: Can you change that code? If so, make it so finally doesn't throw anything at all.

I would also add to your statement that in the
extremely rare case that an Exception thrown from
finally needs to be reported, I think wrapping the
original is acceptable.

You mean doing that wrapping inside finally? Icky bad. There's no reason for any exception--wrapped or otherwise--to be thrown from finally. In the original code, if you get rid of the throw new BarException(); in the finally block, then the method will throw FooException.
 

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



 
I think the stack trace shows it all doesn't it ?
 

Posts:13,769
Registered: 00-11-29
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:40 PM (reply 7 of 84)



 
I think the stack trace shows it all doesn't it ?

No, it shows the method calls and where the exception originates but in this case that's the finally block. The original Exception message is gone.
 

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



 
I think the stack trace shows it all doesn't it ?

Yes. If you wrap an exception with another, the wrapper's printStackTrace() method apparently calls that of the wrappee. However, that's not why you shouldn't throw from finally. You want the exception thrown or the clean return to reflect how the try block completed, not how the cleanup section completed. I suppose there could be a case where this is not true, but I've not seen it, and with my limited imagination, can't see how it could happen.
 

Posts:13,769
Registered: 00-11-29
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:42 PM (reply 9 of 84)



 
You mean doing that wrapping inside finally? Icky bad.
There's no reason for any exception--wrapped or
otherwise--to be thrown from finally. In the original
code, if you get rid of the throw new
BarException();
in the finally block, then the
method will throw FooException.

My gut reaction is completely agree with you. I've just had many experiences where I was sure that something should always or never be done and then learn of exceptions to that rule. I can't think of a reason to do it, but at least the original exception would no be lost.
 

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



 
public class StackTrace {    public static void main(String[] args) {        try {            foo();        }        catch (Exception exc) {            exc.printStackTrace();        }    }     public static void foo() throws Exception {        Exception exc2 = null;        try {            bar();        }        catch (Exception exc) {            exc2 = exc;        }        finally {            if (true) {                throw new Exception("foo", exc2);                             }        }    }     public static void bar() throws Exception {        throw new Exception("bar");    }}  :; java -cp classes StackTracejava.lang.Exception: foo        at StackTrace.foo(StackTrace.java:21)        at StackTrace.main(StackTrace.java:4)Caused by: java.lang.Exception: bar        at StackTrace.bar(StackTrace.java:27)        at StackTrace.foo(StackTrace.java:14)        ... 1 more 
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:45 PM (reply 11 of 84)



 
My gut reaction is completely agree with you. I've
just had many experiences where I was sure that
something should always or never be done and then
learn of exceptions to that rule. I can't think of a
reason to do it, but at least the original exception
would no be lost.

If you're talking about maintaining current behavior but also not losing the original exception, then, sure, wrap it. I'd seriously question the decision that has finally throwing anything in the first place though. Maybe there is a valid reason, and if so, I'd like to see it--I'm always interested in oddities. :-)
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 3:47 PM (reply 12 of 84)



 
I think the stack trace shows it all doesn't it ?

No, it shows the method calls and where the exception
originates but in this case that's the finally block.
The original Exception message is gone.

If you wrap an exception with another one, both stacktraces are shown, as my code demonstrates. If you just replace one exception with another, without wrapping the original inside the new one, then the original's stacktrace is gone.
 

Posts:426
Registered: 11/1/00
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 4:39 PM (reply 13 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.

As an aside, I'm thinking about writing my own JDBC driver wrapper that will Proxy a Connection and intercept the close() method, and return it to the pool...
 

Posts:37,103
Registered: 3/30/99
Re: Catching causal exceptions from finally{} block?  
Aug 2, 2004 5:12 PM (reply 14 of 84)



 
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.

There's a better way to do it. You don't need to keep a temp reference to that exception in your finally block. Finally doesn't need to know anything about the exception.
public void foo() {    try {        Bar bar = sqlStuff();    }     catch (SQLException exc) {        // This catch block will execute if  SQLException is thrown at *1*        System.err.println("I got a SQLException!");    }} private Bar sqlStuff() throws SQLException, MyException {    try {        // *1* do something that might throws SQLException, and maybe something else        return aBar;    }    catch (SomeOtherException exc) {        throw new MyException(exc);    }    finally {        // close ResultSet, Statement, Connection        // NO EXCEPTION re-throwing    }    // or return aBar here} 

If a SQLException is thrown inside the try block, finally will execute, and then the method will throw that original SQL exception. If SomeOtherException is thrown, it will be caught, a new MyException will be created to wrap it, the finally block will execute, and the MyException will be thrown from the method. If everything goes well, the finally block will execute, and the method will return aBar.

All this will happen without the finally block touching or knowing about any exception that was thrown before entering it.
 
This topic has 84 replies on 6 pages.    1 | 2 | 3 | 4 | 5 | 6 | Next »