32

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?

Ajay
  • 7,378
  • 18
  • 57
  • 75

10 Answers10

26

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);
}

Update: since Java 7, the various JDBC interfaces extend java.lang.AutoCloseable and while the above code answers the original question, if you're writing code directly against the JDBC API, it can now be structured:

try (
  Connection connection = getConnection();
  PreparedStatement statement = connection.prepareStatement(...);
  ResultSet resultSet = statement.executeQuery()
)
{
  ...
}
Nick Holt
  • 33,455
  • 4
  • 52
  • 58
  • 8
    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 Aug 26 '09 at 16:57
12

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
  • 31,923
  • 16
  • 73
  • 94
10

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.

Community
  • 1
  • 1
seth
  • 36,759
  • 7
  • 60
  • 57
  • That's not technically the same, but depending on the situation it might do what Ajay wants. – Imagist Aug 26 '09 at 16:07
  • You can of course then abstract that with the Execute Around idiom. – Tom Hawtin - tackline Aug 26 '09 at 16:33
  • @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 Aug 26 '09 at 16:40
  • 3
    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 Aug 26 '09 at 16:41
4

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
  • 10,869
  • 4
  • 55
  • 69
2

In Java 10 you can write:

public void java10() throws SQLException {
    try (var connection = Connections.openConnection();
         var callableStatement = connection.prepareCall("my_call");
         var resultSet = callableStatement.executeQuery()) {

        while (resultSet.next()) {
            var value = resultSet.getString(1);
            System.out.println(value);
        }
    }
}

In Java 7, 8 and 9 you can write:

public void java7() throws SQLException {
    try (Connection connection = Connections.openConnection();
         CallableStatement callableStatement = connection.prepareCall("my_call");
         ResultSet resultSet = callableStatement.executeQuery()) {

        while (resultSet.next()) {
            String value = resultSet.getString(1);
            System.out.println(value);
        }
    }
}

In Java 6 you need to write all these lines:

public void java6() throws SQLException {
    Connection connection = Connections.openConnection();
    try {
        CallableStatement callableStatement = connection.prepareCall("my_call");
        try {
            ResultSet resultSet = callableStatement.executeQuery();
            try {
                while (resultSet.next()) {
                    String value = resultSet.getString(1);
                    System.out.println(value);
                }
            } finally {
                try {
                    resultSet.close();
                } catch (Exception ignored) {
                }
            }
        } finally {
            try {
                callableStatement.close();
            } catch (Exception ignored) {
            }
        }
    } finally {
        try {
            connection.close();
        } catch (Exception ignored) {
        }
    }
}
gepree
  • 617
  • 7
  • 9
1

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

Dewfy
  • 23,277
  • 13
  • 73
  • 121
0

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
  • 90,445
  • 31
  • 189
  • 263
  • I'm not sure I agree with that. To my mind, a failure to close a resource represents a more severe problem than a typical exception that would occur during usage. One should endeavor to keep the inner exception (easier in vb.net than C#) but throw a "more severe" one. – supercat Dec 17 '10 at 03:04
  • If you are reading from the network and you are done, is it really of any consequence that the resource failed to close? It certainly doesn't change anything about the program. – Yishai Dec 21 '10 at 13:38
  • unless it leaves the port open and unusable for anyone else – Sam Brinck Feb 01 '12 at 22:56
0

There is also handy Closeables#closeQuitely method in Google Guava library - it can be used for any Closeable

chipiik
  • 1,970
  • 15
  • 15
0

Can we have try block followed by finally bock and catch block later to that?

Robert Langdon
  • 855
  • 1
  • 11
  • 27
-1

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

rty
  • 34
  • 2