Thursday, October 17, 2013

Chaining exceptions in Java 7

I used to write code like this when transmogrifying an exception:

try {
    // Something broken
} catch (final RandomUninformativeException e) {
    final Bug x = new Bug(format("Sprocket sprung a leak: %s", e));
    x.setStackTrace(e.getStackTrace());
    throw x;
}

The intent was to turn a less meaningful exception into a more meaningful one. This was especially useful for log grepping. Most times I could chain the caught exception in the constructor of the thrown one (new BlahException(message, e)) but some exceptions do not have this constructor (e.g., NullPointerException).

With Java 7 I have a more expressive way:

final Bug x = new Bug(format("Sprocket sprung a leak: %s", e));
x.addSuppressed(e);
throw x

You may add as many suppressed exceptions as you like, they all show up nicely (output from some test code):

java.lang.NullPointerException: Outer!
 at scratch.ExceptionMain.main(ExceptionMain.java:11)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
 Suppressed: java.lang.NullPointerException: Inner!
  at scratch.ExceptionMain.main(ExceptionMain.java:12)
  ... 5 more
 Suppressed: java.lang.NullPointerException: Second!
  at scratch.ExceptionMain.main(ExceptionMain.java:13)
  ... 5 more

No comments: