Views on finally in Java [duplicate] - java

This question already has answers here:
Returning from a finally block in Java
(6 answers)
Closed 6 years ago.
public boolean sendDeviceEvent() {
boolean status = false;
try {
device.sendEvent("blah...blah");
status = true;
} catch (Exception e) {
log.error("Failed to send NodeLowBattery Event - {} {}", createNodeLowBatteryNotification(), e.getCause());
} finally {
return status;
}
}
I would like to know how the above code can be considered bad practise since it returns from finally.
Based on the byte code information, finally doesn't return abruptly and no values are set in finally. How can this be considered bad ?

The point is: that finally statement simply doesn't make any sense. It adds no value whatsoever to your code. This version:
try {
...
return true;
} catch (...) {
log ...
}
return false;
does the very same; without making you start to think: what is that finally good for?
In other words: don't get too hang up on functionality; and forget about readability. You want to able to understand what is going on as quickly as possible. Using finally will definitely make your "brain cpu" spin "harder" ... just because you have to read it, and then digest and resolve to "ah, actually I don't need that at all".
Of course, this is very subtle; but in the end: a file full of subtle things that could be a bit clearer ... still makes up a file much harder to read than it ought to be!
Finally: don't get me wrong: there might be occasions where returning from the finally block could make sense. But - only when other things happen in that block (meaning there is a real need to have that finally block anyway).

Related

In which case should I use System.in.close()?

when I am reading the code of opentsdb:
try {
System.in.close(); // Release a FD we don't need.
} catch (Exception e) {
log.warn("Failed to close stdin", e);
}
After searching this question on the Internet, I can't find a suitable answer. I don't understand why they write system.in.close(), and I want to know if we don't add this code block, what will happen?
Probably only if you used System.setIn() to override the standard input. One normally does not close the standard input, it's handled by JVM process shutdown.

Catching throwable and handling specific exceptions

Ok I know catching throwable is not a good idea:
try {
// Some code
} catch(Throwable e) { // Not cool!
// handle the exception
}
But recently I was reading through an open sourced code and I saw this interesting (at least to me) piece of code:
try {
// Some Code
} catch (Throwable ex){
response = handleException(ex, resource);
}
private handleException(Throwable t, String resource) {
if (t instanceof SQLEXception) {
// Some code
} else if (t instanceof IllegalArgumentException) {
//some code
} //so on and so forth
}
This doesn't seem to be that bad? What is wrong with this approach?
There are various reasons why you should not catch a Throwable. First of all is, that Throwable includes Errors - and there's normally not much an application can do if one of these appears. Also Throwable reduces your chances of finding out, WHAT has happened. All you get is "something bad has happened" - which might be a catastrophe or just a nuisance.
The other aproach is better but of course I still would not catch Throwable, but try to catch more specific Exceptions, if possible at all. Otherwise you are catching everything and then try to sort out which kind of bad thing happened. Your example could be written as...
try {
...
} catch (SQLEXception ex){
response = ... ;
} catch (IllegalArgumentException ex){
response = ...;
}
...which would reduce the amount of if ( ... instanceof ... ) blocks (which are only needed because the author first decided to catch everything in one big bucket). It something actually throws Throwable, then you don't have much choice, of course.
You are right when you say that catching Throwable is not a good idea. However, the code that you present in your question is not catching Throwable in an evil way but let's talk about that later. For now, the code that you present in your question has several advantages :
1. Readability
If you look at the code carefully, you will notice that even though the catch block is catching a Throwable, the handleException method is checking the type of exception thrown and possibly taking different actions based on the exception type.
The code presented in your question is synonymous to saying:
try {
doSomething();
} catch (SQLEXception ex){
response = handleException(resource);
} catch(IllegalArgumentException ex) {
response = handleException(resource);
} catch(Throwable ex) {
response = handleException(resource);
}
Even if you have to catch 10+ exceptions only, this code can easily take up a lot of lines of code and the multi-catch construct is not going to make the code any cleaner. The code that you present in your question is simply delegating the catch to another method to make the actual method that does the work more readable.
2. Reusability
The code for the handleRequest method could easily be modified and placed in a utility class and accessed throughout your application to handle both Exceptions and Errors. You could even extract the method into two private methods; One that handles Exception and one that handles Error and have the handleException method that takes a Throwable further delegate the calls to these methods.
3. Maintainibility
If you decide that you want to change the way you log an SQLExceptions in your application, you have to make this change in a single place rather than visiting every method in every class that throws an SQLException.
So is catching Throwable a bad idea?
The code that you present in your question is not really the same as catching Throwable alone. The following piece of code is a big no-no:
try {
doSomething();
} catch(Throwable e) {
//log, rethrow or take some action
}
You should catch Throwable or Exception as far away in the catch chain as possible.
Last but not the least, remember that the code you present in your question is framework's code and there are certain errors that the framework can still recover from. See When to catch java.lang.Error for a better explanation.
Catching Throwables out of laziness is a bad idea.
This was particularly tempting before try-multi-catch was introduced.
try {
...
} catch (SomeException e) {
//do something
} catch (OtherException e) {
//do the same thing
} ...
Repeating catch blocks is tedious and verbose, so some people decided to just catch Exception or Throwable and be done with it. This is what should be avoided because:
It makes it difficult to follow what you're trying to do.
You may end up catching a lot of stuff you can't deal with.
You deserve bonus punishment if you completely swallow the Throwable in the catch block. (And we've all seen code that does that...:))
But catching Throwables when it is absolutely necessary is fine.
When is it necessary? Very rarely. In framework-style code there are various scenarios (dynamically loading an external class is the most obvious one), in a standalone application a typical example is to attempt to display/log some kind of error message before exiting. (Bearing in mind that the attempt may fail, so you don't want to put anything critical there.)
As a rule of thumb, if there's nothing you can do about an exception/error, you shouldn't catch it at all.
You posted a link to Jongo, which demonstrates one possible use for this technique: re-using error handling code.
Let's say you've got a large block of error handling code that naturally repeats itself in various places in your code - for example Jongo produces standard responses for some standard classes of errors. It may be a good idea to extract that error handling code into a method, so you can re-use it from all the places it's needed.
However, that's not to say that there's nothing wrong with Jongo's code.
Catching Throwable (rather than using multicatch) is still suspicious, as you're likely to catch Errors that you're not really in a position to handle (are you sure you meant to catch ThreadDeath?). In this situation, if you absolutely have to catch Throwable, it'd be better to "catch and release" (i.e, rethrow anything that you didn't mean to catch). Jongo doesn't do this.
There are exactly two valid uses for using a huge net:
If you will handle everything uniformly, like a top-level catch for logging/reporting, possibly followed by an immediate exit.
To reduce duplication, by exporting all the handling into its own method.
Catch the most derived common ancestor there is to avoid extra-work and increase clarity.
DRY is an important design principle.
In both cases, unless you expected that exception and handled it completely, rethrow.
First of all, catching Throwable makes your application rather intransparent. You should be as explicit as possible on catching exceptions to enable good traceability in exceptional cases.
Let's have a look at the method handleException(...) and see some of the problems that occur by this approach:
you catch Throwable but you only handle Exceptions, what happens if an e.g. OutOfMemoryError of type Error is thrown? - I see bad things to happen...
Regarding good object oriented programming using instanceof breaks the Open-Closed-Principle and makes code changes (e.g. adding new exceptions) really messy.
From my point of view, catch-blocks are exactly made for the functionality that are tried to cover in handleExceptions(...), so use them.
Java 7 solves a bit of the tedium that is multi-catching of similar exceptions with similar handling. You definitely should not be doing what the person has done here. Just catch the appropriate exceptions as needed, it may look ugly but then that's what throws is for, pass it to the method that should catch it and you shouldn't be wasting too much code space.
Check out this link for more information.
Just to provide balance - there is one place where I will always catch (Throwable):
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
At least something shows somewhere that something went wrong.
You can always catch different type of exceptions and perform some operations based on the type of the exception you got.
Here is an example
try{
//do something that could throw an exception
}catch (ConnectException e) {
//do something related to connection
} catch (InvalidAttributeValueException e) {
// do anything related to invalid attribute exception
} catch (NullPointerException e) {
// do something if a null if obtained
}
catch (Exception e) {
// any other exception that is not handled can be catch here, handle it here
}
finally{
//perform the final operatin like closing the connections etc.
}

return statement - finally block does not complete normally [duplicate]

This question already has answers here:
Behaviour of return statement in catch and finally
(8 answers)
Closed 8 years ago.
Similar question has been asked here. But that does not provide answer.
try {
object = (Dev)Class.forName("Dev").newInstance();
} catch (Exception e)
{
throw new RuntimeException("Devis not available");
}
finally
{
return object;
}
But finally block gives warning :
finally block does not complete normally
But as per my understating, finally block always gets executed and will return the object. Why warning says that it will not get completed normally?
The problem is that the finally block would remove any exceptions being thrown since it would issue a "normal" return.
From the JLS spec:
Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.
and (more relevant in your case):
Note that abrupt completion of a finally clause can disrupt the transfer of control initiated by a throw statement.
There are so many explanations about the finally block in a try-catch-finally statement. Go and search for it.
Quick explanation anyway: The finally block is always run, regardless whether an exception was thrown (and maybe caught) or not. If a finally block terminates in an unnormal way (such as itself throwing an excpetion or returning a value) this will always override what was done in the try block or a catch block. That also means that these are got lost.
The conclusion: Never throw an exception ot return a value from the finally block. Only use it for cleaning up processes.
try this. If you are throwing an exception than there is something wrong with object. just return it before the catch.
try {
object = (Dev)Class.forName("Dev").newInstance();
return object;
} catch (Exception e)
{
throw new RuntimeException("Devis not available");
}
Returning from finally is a bad practice in java.
It may result in many unexpected outputs. Check below link for some of such examples:
http://www.cs.arizona.edu/projects/sumatra/hallofshame/
Anyways found few links related to this finally block, Follow the below links for answers related to that.
Does finally always execute in Java?
Returning from a finally block in Java

Java: commit vs rollback vs nothing when semantics is unchanged?

Ok, I know the difference between commit and rollback and what these operations are supposed to do.
However, I am not certain what to do in cases where I can achieve the same behavior when using commit(), rollback() and/or do nothing.
For instance, let's say I have the following code which executes a query without writing to db:
I am working on an application which communicates with SQLite database.
try {
doSomeQuery()
// b) success
} catch (SQLException e) {
// a) failed (because of exception)
}
Or even more interesting, consider the following code, which deletes a single row:
try {
if (deleteById(2))
// a) delete successful (1 row deleted)
else
// b) delete unsuccessful (0 row deleted, no errors)
} catch (SQLException e) {
// c) delete failed (because of an error (possibly due to constraint violation in DB))
}
Observe that from a semantic standpoint, doing commit or rollback in cases b) and c) result in the same behavior.
Generally, there are several choices to do inside each case (a, b, c):
commit
rollback
do nothing
Are there any guidelines or performance benefits of choosing a particular operation? What is the right way?
Note: Assume that auto-commit is disabled.
If it is just a select, I wouldn't open a transaction and therefore, there is nothing to do in any case. Probably you already know is there is an update/insert since you have already passed the parameters.
The case where you intend to do a manipulation is more interesting. The case where it deletes is clear you want to commit; if there is an exception you should rollback to keep the DB consistent since something failed and there is not a lot you can do. If the delete failed because there was nothing to delete I'd commit for 3 reasons:
Semantically, it seems more correct since the operation was
technically successful and performed as specified.
It is more future proof so if somebody adds more code to the
transaction they won't be surprised with it is rolling back because
one delete just didn't do anything (they would expect on exception
that the transaction is rolled back)
When there is an operation to do, commit is faster but in this case I
don't think it matters.
Any non-trivial application will have operations requiring multiple SQL statements to complete. Any failure happening after the first SQL statement and before the last SQL statement will cause data to be inconsistent.
Transactions are designed to make multiple-statement operations as atomic as the single-statement operations you are currently working with.
I've asked myself the exact same question. In the end I went for a solution where I always commited successful transactions and always rollbacked non-successful transactions regardles of it having any effect. This simplified lot of code and made it clearer and more easy to read.
It did not have any major performance problems in the application I worked in which used NHibernate + SQLite on .net. Your milage may vary.
As others stated in their answers, it's not a matter of performance (for the equivalent cases you described), which I believe is negligible, but a matter of maintainability, and this is ever so important!
In order for your code to be nicely maintainable, I suggest (no matter what) to always commit at the very bottom of your try block and to always close your Connection in your finally block. In the finally block you also should rollback if there are uncommitted transactions (meaning that you didn't reach the commit at the end of the try block).
This example shows what I believe is the best practice (miantainability-wise):
public boolean example()
{
Connection conn;
...
try
{
...
//Do your SQL magic (that can throw exceptions)
...
conn.commit();
return true;
}
catch(...)
{
...
return false;
}
finally
{//Close statements, connections, etc
...
closeConn(conn);
}
}
public static void closeConn(Connection conn)
{
if (conn != null)
if (!conn.isClosed())
{
if (!conn.getAutoCommit())
conn.rollback();//If we need to close() but there are uncommitted transacitons (meaning there have been problems)
conn.close();
conn = null;
}
}
What you are saying depends upon the code being called, does it return a flag for you to test against, or does it exclusively throw exceptions if something goes wrong?
API throws exceptions but also returns a boolean (true|false):
This situation occurs a lot, and it makes it difficult for the calling code to handle both conditions, as you pointed out in your OP. The one thing you can do in this situation is:
// Initialize a var we can test against later
// Lol, didn't realize this was for java, please excuse the var
// initialization, as it's demonstrative only
$queryStatus = false;
try {
if (deleteById(2)) {
$queryStatus = true;
} else {
// I can do a few things here
// Skip it, because the $queryStatus was initialized as false, so
// nothing changes
// Or throw an exception to be caught
throw new SQLException('Delete failed');
}
} catch (SQLException $e) {
// This can also be skipped, because the $queryStatus was initialized as
// false, however you may want to do some logging
error_log($e->getMessage());
}
// Because we have a converged variable which covers both cases where the API
// may return a bool, or throw an exception we can test the value and determine
// whether rollback or commit
if (true === $queryStatus) {
commit();
} else {
rollback();
}
API exclusively throws exceptions (no return value):
No problem. We can assume that if no exception was caught, the operation completed without error and we can add rollback() / commit() within the try/catch block.
try {
deleteById(2);
// Because the API dev had a good grasp of error handling by using
// exceptions, we can also do some other calls
updateById(7);
insertByName('Chargers rule');
// No exception thrown from above API calls? sweet, lets commit
commit();
} catch (SQLException $e) {
// Oops exception was thrown from API, lets roll back
rollback();
}
API does not throw any exceptions, only returns a bool (true|false):
This goes back to old school error handling/checking
if (deleteById(2)) {
commit();
} else {
rollback();
}
If you have multiple queries making up the transaction, you can borrow the single var idea from scenario #1:
$queryStatus = true;
if (!deleteById(2)) {
$queryStatus = false;
}
if (!updateById(7)) {
$queryStatus = false;
}
...
if (true === $queryStatus) {
commit();
} else {
rollback();
}
"Note: Assume that auto-commit is disabled."
Once you disable auto-commit, you are telling the RDBMS that you are taking control of commits from now until auto-commit is re-enabled, so IMO, it's good practice to either rollback or commit the transaction versus leaving any queries in limbo.

Java unreported exception [duplicate]

This question already has an answer here:
What does "error: unreported exception <XXX>; must be caught or declared to be thrown" mean and how do I fix it?
(1 answer)
Closed 8 months ago.
While learning Java I stumble upon this error quite often. It goes like this:
Unreported exception java.io.FileNotFound exception; must be caught or declared to be thrown.
java.io.FileNotFound is just an example, I've seen many different ones. In this particular case, code causing the error is:
OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("myfile.pdf")));
Error always disappears and code compiles & runs successfully once I put the statement inside try/catch block. Sometimes it's good enough for me, but sometimes not.
First, examples I'm learning from do not always use try/catch and should work nevertheless, apparently.
Whats more important, sometimes when I put whole code inside try/catch it cannot work at all. E.g. in this particular case I need to out.close(); in finally{ } block; but if the statement above itself is inside the try{ }, finally{} doesnt "see" out and thus cannot close it.
My first idea was to import java.io.FileNotFound; or another relevant exception, but it didnt help.
What you're referring to are checked exceptions, meaning they must be declared or handled. The standard construct for dealing with files in Java looks something like this:
InputStream in = null;
try {
in = new InputStream(...);
// do stuff
} catch (IOException e) {
// do whatever
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
}
}
}
Is it ugly? Sure. Is it verbose? Sure. Java 7 will make it a little better with ARM blocks but until then you're stuck with the above.
You can also let the caller handle exceptions:
public void doStuff() throws IOException {
InputStream in = new InputStream(...);
// do stuff
in.close();
}
although even then the close() should probably be wrapped in a finally block.
But the above function declaration says that this method can throw an IOException. Since that's a checked exception the caller of this function will need to catch it (or declare it so its caller can deal with it and so on).
Java's checked exceptions make programmers address issues like this. (That's a good thing in my opinion, even if sweeping bugs under the carpet is easier.)
You should take some appropriate action if a failure occurs. Typically the handling should be at a different layer from where the exception was thrown.
Resource should be handled correctly, which takes the form:
acquire();
try {
use();
} finally {
release();
}
Never put the acquire() within the try block. Never put anything between the acquire() and try (other than a simple assign). Do not attempt to release multiple resources in a single finally block.
So, we have two different issues. Unfortunately the Java syntax mixes up the two. The correct way to write such code is:
try {
final FileOutputStream rawOut = new FileOutputStream(file);
try {
OutputStream out = new BufferedOutputStream(rawOut);
...
out.flush();
} finally {
rawOut.close();
}
} catch (FileNotFoundException exc) {
...do something not being able to create file...
} catch (IOException exc) {
...handle create file but borked - oops...
}

Categories

Resources