Search code examples
javaexceptiontransactionserror-handling

Rethrowing checked exceptions


public void foo() {
 begin();
 try {
  ...
  commit();
 } catch (Exception e) {
  rollback();
  throw e;
 }
}

In the sample above, there is an error because foo has no throws Exception. Adding that wouldn't make do the method's usability a lot of good either.

What's the best way to do this? How do you do something if an error occurs without really "handling" the error?


Solution

  • At least two approaches come to mind, which are usually going to be combined depending on what you want foo to do:

    1. Catch and rethrow only the relevant exceptions

    There are only so many exceptions the code in your main flow can throw (probably mostly SqlExceptions). So only catch and rethrow those, and declare that you're doing so. More to the point, rethrow only the ones you're not actually handling (in your simplified sample code, you're not handling any, but your real life code is probably more subtle).

    Mind you, some of the exceptions may be runtime exceptions, and so you may want to combine this with the below.

    2. Don't catch the exception at all

    Like this:

    // Signature changes to include any exceptions that really can be thrown
    public void foo() throws XYZException, ABCException {
     // A flag indicating that the commit succeeded
     boolean done = false;
    
     begin();
     try {
      // Don't have any `return` statements in here (or if you do,
      // set `done` to `true` first)
    
      ...
      commit();
      done = true; // Commit didn't throw an exception, we're done
     } finally {
      // finally clause always happens regardless
      if (!done) {
        // We must be processing an exception; rollback
        try {
          rollback();
        } catch (Exception e) {
          // quash it (e.g., leave this block empty), we don't want
          // to mask the real exception by throwing a different one
        }
      }
     }
    }
    

    Naturally your signature needs to include any exceptions that may be thrown in the main flow, but that's what you're trying to do, if I'm understanding you correctly.

    Again, you may well combine these two approaches, because you may want to handle some exceptions and not others.