views:

1709

answers:

12

Connection.close() may throw SqlException, but I have always assumed that it is safe to ignore any such exceptions (and I have never seen code that does not ignore them).

Normally I would write:

 try{
    connection.close();
 }catch(Exception e) {}

Or

 try{
    connection.close();
 }catch(Exception e) {
     logger.log(e.getMessage(), e); 
 }

The question is:

  1. Is it bad practice (and has anyone had problems when ignoring such exceptions).
  2. When Connection.close() does throw any exception.
  3. If it is bad how should I handle the exception.

Comment:

I know that discarding exceptions is evil, but I'm reffering only to exceptions thrown when closing a connection (and as I've seen this is fairly common in this case).

Does anyone know when Connection.close() may throw anything?

+9  A: 

In general, I've had days wasted by people throwing away exceptions like that.

I recommend following a few basic rules with exceptions:

If you are ABSOLUTELY SURE you will NEVER cause a problem with a checked exception, catch JUST that exception and comment exactly why you don't need to handle it. (Sleep throws an InterruptedException that can always be ignored unless you actually are interested in it, but honestly this is the only case I usually ignore--even at that, if you never get it, what's the cost of logging it?)

If you are not sure, but you may get it occasionally, catch and log a stack trace just so that if it is causing a problem, it can be found. Again, catch only the exception you need to.

If you don't see any way the checked exception can be thrown, catch it and re-throw it as an unchecked exception.

If you know exactly what is causing the exception, catch it and log exactly why, you don't really need a stack trace in this case if you are very clear as to what's causing it (and you might mention the class that's logging it if you're not already using log4j or something.

It sounds like your problem would fall into the last category, and for this kind of a catch, never do what you wrote (Exception e), always do the specific exception just in case some unchecked exception is thrown (bad parameters, null pointer, ...)

Update: The main problem here is that Checked Exceptions are ungood. The only highly used language they exist in is Java. They are neat in theory, but in action they cause this behavior of catch and hide that you don't get with unchecked exceptions.

A lot of people have commented on the fact that I said that hiding them is okay sometimes. To be specific, the one case I can think of is:

try {
    Thread.sleep(1000);
catch (InterruptedException e) {
    // I really don't care if this sleep is interrupted!
}

I suppose the main reason I feel this use is okay is because this use of InterruptedException is an abuse of the checked exception pattern in the first place, it's communicating the result of a sleep more than indicating an exception condition.

It would have made much more sense to have:

boolean interrupted=Thread.sleep(1000);

But they were very proud of their new checked exception pattern when they first created Java (understandably so, it's really neat in concept--only fails in practice)

I can't imagine another case where this is acceptable, so perhaps I should have listed this as the single case where it might be valid to ignore an exception.

Bill K
It is *never* a good idea to ignore an exception, even if you comment why. There is minimal overhead to logging the exception, and that is the minimum that should be done, cause while you are "...ABSOLUTELY SURE you will NEVER cause a problem...", problems occur later, not now.
Spencer K
My biggest case for this is sleep() It throws a checked exception that more often than not can never be reached, and if it is reached, who cares? If I cared (of course), I'd handle it. But still, comment it.
Bill K
I once worked on a system that was littered with suppressed try catches, and most were commented with "this should never happen". They're right, errors should never happen, but they do. Lesson I learned, never suppress an exception. Inevitably they do happen.
Jeremy
Jeremy: I clarified my post re "eating" an exception. If you think we weren't in agreement, you misunderstood the post a little though, because I recommend that anything that "Should never happen" should be caught and rethrown as a unchecked exception because you are completely right.
Bill K
+3  A: 

I personally like your second idea of at least logging the error. Because you're catching Exception, it's theoretically possible to catch something other than a SQL Exception. I'm not sure what could happen or how rare (like out of memory exceptions, etc) but supressing all errors doesn't seem right to me.

If you want to suppress errors, I would do it only to very specific ones you know should be handled that way.

Hypothecial situation: what if your sql had an open transaction, and closing the connection caused an exceptino because of that, would you want to suppress that error? Even suppressing SQLExceptions might be a little dangerous.

Jeremy
+1  A: 

You have to handle the exception. It is not a bad practice. Imagine you lost the network just before closing the dabatase connection. It will probably throw the exception.

Is it rare ? Yes. I suppose that's what they are called exceptions and that is not a reason to ignore it. Remember that if it could fail, it will fail.

You should also think about whether it is possible to have a null connection at this point (it would cause a NullPointerException) or not.

if (connection != null) {
   try { 
      connection.close(); 
   } catch (SQLException sqle) { 
      logger.log(e.getMessage(), e); 
   }
}
Guido
A: 

From my experience ignoring an exception is never a good idea. Believe me, the production support engineers and analysts will thank you a tonne if you logged the exception.

Also, if you are using the right Logging framework, there would be zero or minimal performance impact of the exception.

a-sak
A: 

In an ideal world, you should never do nothing on an exception, of course, in an ideal world, you would never get an exception either 8-)

So, you have to examine the impacts of the various options.

Log only: Database operations are all finished, nothing left to do but clean up the resources. If an exception occurs at this point, it most likely has no impact on the work performed, so logging the error should suffice. Of course, if an error occurs during logging, then you basically have to handle failed database operation that didn't actually fail.

Empty handler: Database operations are all finished, nothing left to do but clean up the resources. If an exception occurs at this point, it most likely has no impact on the work performed, so the method returns successfully. The next database access may run into the same problem, but it should occur at the start of a transaction, where it will rightly fail and then get handled appropriately. If the problem has fixed itself, then there will be no indication that anything ever went wrong.

It is a pretty typical scenario to put a close() operation(s) in a finally block to ensure that cleanup occurs, since we don't want any other failures to inhibit the resource cleanup. If no error has occurred, then your method should not fail when its operation has successfully completed. In this case, empty exception handling is quite normal.

Of course opinions will vary.

Robin
+5  A: 

At the very minimum, always always always log exceptions that you are catching and not acting on.

Silently caught exceptions that are swallowed without the tiniest peep are the worst.

matt b
I believe you have had to debug such code, before you see the value of doing so.
Thorbjørn Ravn Andersen
A: 

if this is an "error that never happens" case then I will just rethrow an Exception and hope no one catches it.
if this is any other case I will probably log it

SWD
A: 

You could also throw a RuntimeException:

try {
    connection.close();
 } catch(Exception e) {
     throw new RuntimeException(e); 
 }

You won't have to change your method signature and will be able to use the Exception.getCause method later on to find the cause of the problem.

Fábio
This is a really good solution to a lot of checked exceptions. I'm not sure why you were voted down for it, I fixed it for you :) In practice you probably want to create a more specific runtime exception to rethrow it as.
Bill K
What is the reason to throw it as a runtime exception?
DMKing
ALWAYS include the _reason_ why you are wrapping and rethrowing as the message. Remember, the more information you have in a stack trace, the more helpful it is to the person trying to figure out what happened. Especially if that person is not familiar with the code.
Thorbjørn Ravn Andersen
+4  A: 

hi there,

Actually, what you're doing is (almost) best practice :-) here's what I saw in Spring's JdbcUtils.java. So, you might want to add another Catch block.

/**
 * Close the given  ResultSet and ignore any thrown exception.
 * This is useful for typical finally blocks in manual  code.
 * @param resultSet the  ResultSet to close
 * @see javax.resource.cci.ResultSet#close()
 */
private void closeResultSet(ResultSet resultSet) {
  if (resultSet != null) {
    try {
      resultSet.close();
    }
    catch (SQLException ex) {
      logger.debug("Could not close  ResultSet", ex);
    }
    catch (Throwable ex) {
      // We don't trust the  driver: It might throw RuntimeException or Error.
      logger.debug("Unexpected exception on closing  ResultSet", ex);
    }
  }
}
anjanb
A: 

Why I am closing the Connection in my java application/EJB ? If I didn't close that connection, it cause the DB server performance?

+1  A: 

Note that Apache Commons DButils provides a closeQuietly() method, that you can use to avoid cluttering your code with 'redundant' catches. Note I'm not advocating swallowing exceptions, but for this close() scenario I think it's generally acceptable.

Brian Agnew
Proper error handling of closes is actually hard to get right.
Thorbjørn Ravn Andersen
A: 

If you can handle it, then do so (and log it if it was unexpected). If you cannot handle it, then rethrow it properly so some code above can handle it.

Silently swallowing exceptions is leaving out crucial information for the person to fix the code.

Thorbjørn Ravn Andersen