try-with-resources and catching Exceptions which are both thrown during normal execution and autoClose

33 Views Asked by At

I am pondering for a while with the following code:

try (Connection conn = dbHandler.getConnection()) {
   // do something with the connection
   dbConn.commit();
} catch (SQLException e) {
   System.err.println("Too bad!");
   e.printStackTrace();
}

Consider my application needs to be resilient to some SQL locking/dead-lock situations, so I would need to do some specific handling inside of the catch block. However, I cannot easily identify, if the exception was thrown during the "do something" part of my code or during autoClose(). And of course, each JDBC driver throws slightly different exceptions and if you throw JDBI in the mix, it gets even more complicated. So you can't really rely on different catch clauses do precisely identify, when the exception got thrown.

The only solution I could come up with is this code:

boolean finishedProcessing = false;
try (Connection conn = dbHandler.getConnection()) {
   // do something with the connection
   dbConn.commit();
   finishedProcessing = true;
} catch (SQLException e) {
   if (finishedProcessing) {
      // this is an exception during autoClose
      System.err.println("Too bad!");
      e.printStackTrace();
   } else {
      // handle rollback cases, retries etc
      System.err.println("SQL recovery performed.");
      throw e;
   }
}

Now the same issue comes up with IOExceptions for File* operations and probably in many other cases.

To be honest, I am just hoping I missed something completely obvious and I appreciate any insight from the Java experts out here.

As stated above, the only solution I found so far is introducing state-variables into the code, which doesn't really make sense to me. I am fully aware of suppressing exceptions from the autoClose process, when an exception got thrown by the try block, however, as stated above the same kind of exception can be thrown, suppressed and both.

1

There are 1 best solutions below

2
Abra On

Don't use try-with-resources and add a finally block.

Connection conn = null;
try {
    conn = dbHandler.getConnection()
    // do something with the connection
    dbConn.commit();
}
catch (SQLException e) {
    // Handle rollback cases, retries, etc.
    System.err.println("SQL recovery performed.");
    e.printStackTrace();
}
finally {
    if (conn != null) {
        try {
            conn.close();
        }
        catch (SQLException xSql) {
            System.out.println("Failed to close database connection.");
            xSql.printStackTrace();
        }
    }
}