Compiler warning re finally

R

Rhino

I've got a compiler warning that has me quite baffled.

Here is my code:

if (sqlCode != 0 || !sqlState.equals("00000")) {
System.err.println("Stored procedure " + STORED_PROCEDURE_NAME + "
failed.");
System.err.println("SQLState = " + sqlState);
System.err.println("SQLCode = " + sqlCode);
System.err.println("SQLMessage = " + sqlMessage);
System.err.println("ProcMessage = " + procMessage);
System.err.println("StackTrace:\n" + stackTrace);
try {
conn01.rollback();
}
catch(SQLException sql_excp) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Encountered error
while " +
"attempting to roll back.");
sql_excp.printStackTrace();
}
finally {
return;
}
}

and here is the warning:

finally block does not complete normally


I don't have much experience with finally but, as far as I can tell, I'm not
doing anything odd here. If I get an error from my database call, I want to
print some diagnostics and attempt to rollback the transaction, then return
from the method. If the rollback fails, I want to print some additional
diagnostics and, again, return from the method.

Is there a problem with doing a return in a finally block? If there is some
sort of problem with my approach, can anyone suggest an alternative way of
accomplishing the same thing?

I'm running Eclipse 3.0.1 on Windows XP.

--
Rhino
---
rhino1 AT sympatico DOT ca
"There are two ways of constructing a software design. One way is to make it
so simple that there are obviously no deficiencies. And the other way is to
make it so complicated that there are no obvious deficiencies." - C.A.R.
Hoare
 
D

dar7yl

You are misinterpreting what the finally clause does.

a.. The finally statement must be associated with a try statement and
identifies a block of statements that are executed regardless of whether or
not an error occurs within the try block. (from the java tutorial)

When an exception is thrown, control is passed to each catch block on the
stack, in reverse order of nesting until the exception matches the catch
type. Each passed-over try/catch block is checked to see if it has a
finally clause, and if so, the finally is executed (consider it like a
subroutine) .

You might consider putting your return in the catch, not the finally.
 
R

Rhino

I just reviewed the Catching and Handling Exceptions section in the Java
Tutorial (Catching and Handling Exceptions). Frankly, I still don't see
anything wrong with my code, according to the information there.

The rollback() method of the Connection class *can* throw an SQLException so
I have a catch block for it; regardless of whether the rollback() works or
fails, I still want to return. Isn't 'finally' the right way to accomplish
that?

By the way, I got rid of the compile warning by removing the finally block
and simply following the catch with a 'return':

if (sqlCode != 0 || !sqlState.equals("00000")) {
System.err.println("Stored procedure " + STORED_PROCEDURE_NAME + "
failed.");
System.err.println("SQLState = " + sqlState);
System.err.println("SQLCode = " + sqlCode);
System.err.println("SQLMessage = " + sqlMessage);
System.err.println("ProcMessage = " + procMessage);
System.err.println("StackTrace:\n" + stackTrace);
try {
conn01.rollback();
}
catch(SQLException sql_excp) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Encountered error
while " +
"attempting to roll back.");
sql_excp.printStackTrace();
}
return;
}

This makes the compiler happy and should accomplish exactly what I want to
do. But why doesn't the compiler like the way I used finally in the original
version of the code?

Rhino
 
D

dar7yl

Rhino said:
I just reviewed the Catching and Handling Exceptions section in the Java
Tutorial (Catching and Handling Exceptions). Frankly, I still don't see
anything wrong with my code, according to the information there.

The rollback() method of the Connection class *can* throw an SQLException
so
I have a catch block for it; regardless of whether the rollback() works or
fails, I still want to return. Isn't 'finally' the right way to accomplish
that?

No, finally is always called whether or not an exception is thrown. You
would, in essence be returning even if no error occured.
By the way, I got rid of the compile warning by removing the finally block
and simply following the catch with a 'return':

if (sqlCode != 0 || !sqlState.equals("00000")) { ...
try {
conn01.rollback();
}
catch(SQLException sql_excp) {
System.err.println(CLASS_NAME + "." + METHOD_NAME + " - Encountered
error
while " +
"attempting to roll back.");
sql_excp.printStackTrace();
}
return;
}

This makes the compiler happy and should accomplish exactly what I want to
do. But why doesn't the compiler like the way I used finally in the
original
version of the code?

Because finally is not executed in the calling environment, but in the
exception environment.
ie, 'finally' has no point to return from.

Putting the return statement at the end of your function is redundant.
Why not put the return within the catch, so that it would return IFF there
was an error?
That way, you can put success-dependant code after the try block. Any
cleanup can be done in the finally block WHICH ALWAYS EXECUTES, regardless
of whether an exception is thrown or not.

regards,
Dar7yl
 
C

Chris Smith

Rhino said:
I just reviewed the Catching and Handling Exceptions section in the Java
Tutorial (Catching and Handling Exceptions). Frankly, I still don't see
anything wrong with my code, according to the information there.

The rollback() method of the Connection class *can* throw an SQLException so
I have a catch block for it; regardless of whether the rollback() works or
fails, I still want to return. Isn't 'finally' the right way to accomplish
that?

No, it isn't. Returning from a finally block will cause your code to
ALWAYS complete normally. That means that regardless of what happens
(not just SQLException, but also java.lang.InternalError, for example)
your code will complete normally. That's not what you want to happen
regardless of whether you think it is or not.

Better to do as you later did: catch the SQLException, and allow the
finally block to complete normally. That way you aren't masking
application bugs detected at runtime, assertion failures, serious
problems in your VM process, etc.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
R

Ryan Stewart

Rhino said:
I've got a compiler warning that has me quite baffled. [...]
finally block does not complete normally
[...]
The other posts have gone quite in depth. To put it briefly, it is a very bad
idea to have a finally clause complete abruptly. It can cause your code to
behave in unexpected ways. See section 14.19.2 of JLS 2.0 to see how
try-catch-finally blocks work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top