2

I want to nest a try catch without having a catch in the inner try.
For example:

try (Connection conn = new Connection()) {
    //Fill preparedStatement etc
    try (ResultSet rs = conn.execute()){
    }
} catch (SQLException e) {
    //Log both exceptions here
}

Is this possible and is it a good practice?

Luud van Keulen
  • 1,204
  • 12
  • 38
  • 2
    Why not just put the statements in the try, if anyone throw exception it will be caught by the outer catch block. – Smit May 02 '17 at 13:32
  • @Smit This is a simplified version. I need to do some things with connection first. Also it doesn't close the connection the way you said. – Luud van Keulen May 02 '17 at 14:00
  • Hi @Luud van Keulen, I assume this is the new approach introduced in java7. try with resources are useful to avoid exceptions during resource close statement so that they can not override real exceptions at runtime. so you can use this try only for assign any resource statement not the actual implementation – PrabaharanKathiresan May 02 '17 at 14:07
  • What happened when you tried it? – user207421 May 08 '17 at 09:59
  • It does seem to work. I don't know how to raise an ResultSet exception though so I don't know if it will catch it properly. – Luud van Keulen May 08 '17 at 09:59

2 Answers2

1

You can do this:

try (Connection conn = new Connection()) {
    ResultSet rs = conn.execute()
    // do stuff with rs
} catch (SQLException e) {
    // handle exception
}

Exceptions thrown by conn.execute() will be caught by the catch block. Exceptions thrown by new Connection() will be suppressed:

An exception can be thrown from the block of code associated with the try-with-resources statement. In the example writeToFileZipFileContents, an exception can be thrown from the try block, and up to two exceptions can be thrown from the try-with-resources statement when it tries to close the ZipFile and BufferedWriter objects. If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown by the writeToFileZipFileContents method. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.

See: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

EDIT: As Timothy pointed out, Connection does not guarantee to close a ResultSet it created. So we need something like this:

try (Connection conn = new Connection(); 
     Statement statement = connection.createStatement()) {

    // statement.set(....)

    try (ResultSet rs = conn.execute()) {
        // do stuff with rs
    }

} catch (SQLException e) {
    // handle exceptions
}
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
  • It doesn't properly close this way. – Luud van Keulen May 02 '17 at 13:42
  • Ah you're right, Connection does not promise to close ResultSet it created. – Adriaan Koster May 08 '17 at 09:32
  • So it is a good practice to nest a try witouth the catch block? – Luud van Keulen May 08 '17 at 09:39
  • @LuudvanKeulen Closing the `ResultSet` is exactly what `Connection.close()` *does* promise, via `Statement.close()`. The only (minor) issue with this code is that it could have included the `ResultSet` in the resources to be closed, instead of allocating it separately inside the `try` block. – user207421 May 08 '17 at 10:01
  • @EJP I have read the following: `In any case, it's a good practice to always close ResultSet and Statement explicitly and not to rely on Connection.close.` source: http://stackoverflow.com/a/14024393/5333805 – Luud van Keulen May 08 '17 at 10:19
  • Connection.close() does not guarantee to close underlying ResultSets. That promise is made by Statement, but not by Connection, see the API. – Adriaan Koster May 08 '17 at 11:35
  • @LuudvanKeulen Yes, having a try-with-resources without catch/finally blocks is perfectly normal. – Adriaan Koster May 08 '17 at 11:36
  • @AdriaanKoster `Connection.close()` promises to close '*all* JDBC resources'. See the API. – user207421 May 09 '17 at 21:32
  • @EJP I don't see the word 'all' anywhere. In the Java 7 API it says: "Releases this Connection object's database and JDBC resources immediately". So the question is if the underlying resultsets are considered to belong to the Connection instance. By comparison, the API of Statement has the same sentence, but also the following: "Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.". This leads me to think that it is explicitly guaranteed by Statement, but not so much by Connection. – Adriaan Koster May 12 '17 at 13:44
0

yes, but better is

try (Connection conn = new Connection(); ResultSet rs = conn.execute();){
    } catch (SQLException e) {
    //Log both exceptions here
}
Timothy Truckle
  • 15,071
  • 2
  • 27
  • 51