views:

1006

answers:

7

I have often come across situations like :-

try{ 
     ...
     stmts
     ...
} 
catch(Exception ex) {
     ... 
     stmts
     ... 
} finally {
     connection.close // throws an exception
}

which still needs a try - catch block inside finally.

What is the best practice to overcome this?

+9  A: 

I usually did it this way:

try {
    try {
        ..
        stmts
        ...
    }
    finally {
       connection.close():
    }
} catch (Exception ex) {
     ..
     stmts
     ..    
}

I usually only used this when I wasn't using a library that took care of this plumbing for me.

As Imagist points out, this isn't technically the same as the finally will run before the catch but I think it solves the problem you were trying to solve.

seth
That's not technically the same, but depending on the situation it might do what Ajay wants.
Imagist
@Imagist: Good point. I'll update my answer. Thanks.
seth
You can of course then abstract that with the Execute Around idiom.
Tom Hawtin - tackline
@tackline: thanks! Hadn't seen that before. Here's a link about it for others that are interested: http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom
seth
The thing with this approach is that typically you don't want to do the same thing with exceptions related to the close as you do with exceptions in the main body of the method - and worse, this code would swallow exceptions in the main body if the finally threw an exception.
Yishai
+14  A: 

Write a SQLUtils class that contains static closeQuietly methods that catch and log such exceptions, then use as appropriate.

You'll end up with something that reads like this:

public class SQLUtils 
{
  private static Log log = LogFactory.getLog(SQLUtils.class);

  public static void closeQuietly(Connection connection)
  {
    try
    {
      if (connection != null)
      {
        connection.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing connection.", e);
    }
  }

  public static void closeQuietly(Statement statement)
  {
    try
    {
      if (statement!= null)
      {
        statement.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing statement.", e);
    }
  }

  public static void closeQuietly(ResultSet resultSet)
  {
    try
    {
      if (resultSet!= null)
      {
        resultSet.close();
      }
    }
    catch (SQLExcetpion e)
    {
      log.error("An error occurred closing result set.", e);
    }
  }
}

And your client code will be something like:

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try 
{
  connection = getConnection();
  statement = connection.prepareStatement(...);
  resultSet = statement.executeQuery();

  ...
}
finally
{
  SQLUtils.closeQuietly(resultSet);
  SQLUtils.closeQuietly(statment);
  SQLUtils.closeQuietly(connection);
}
Nick Holt
This is my choice as well in the past, but I have found these days that there are classes, like apache commons DBUtil, that do this for you.
Chris Kessel
looks like a good option :) Thanks
Ajay
+2  A: 

Don't hesitate use one more try ... catch inside finally.

Dewfy
A: 

just remember .. finally always get execute either with try or catch ..

rty
Your point being ?
Silence
didnt get your point
Ajay
A: 

Generally you don't want to do anything more than log an exception which happens when closing a resource, so it should really go in its own try/catch. However, this is generic code that will happen often, so Don't Repeat Yourself, and put the close in a static method (as Nick Holt suggests) that way you won't have the two try/catch items in the same method, making the code easier to read and follow.

Yishai
+1  A: 

Commons-io also has closeQuietly() for in and output streams. I'm using it all the time. It makes your code much more readable.

Wilfred Springer
+4  A: 

As others have mentioned, a static closeQuietly utility is the way to go. One thing to add - if you are in the world of java.io rather than java.sql then there is a useful interface for exactly this purpose - java.io.Closeable

All the data sources and sinks in java.io implement this interface - all streams, channels, writers and readers. That way you can create a single utility to cope with the same "exception on close()" issue without requiring many overloaded versions.

e.g.

public class IoUtils {

  public static closeQuietly (Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException logAndContinue) {
      ...
    }
  }

}
serg10