views:

78

answers:

3

Possible Duplicate:
Unchecked exceptions in Java: Inherit from Error or RuntimeException?

Looking at how our applications do error handling, we have been steadily moving from a checked ExceptionHierarchy (e.g. Exception -> ApplicationException -> SomethingSpecificBadHappenedException) since in many cases we have many long call chains that just pass up ApplicationException, and it adds little value but cluttering our API (we increasingly agree with the opinions expressed in: Effective Exceptions.

In redesigning our error handling around unchecked exceptions, aligned with a "fault barrier" approach, we initially have started working with a RuntimeException based hierarchy, similar to the example in the Spring Data Access layer

We've been starting to wonder if it would be more clear to have them descend from Error, especially around the fact that it would let us do something like a:

} catch (Exception e) {

within our application in a number of spots, but then differentiate with:

} catch (Throwable t) { or } catch (Error err) {

which feels cleaner, though I can't think of major examples of APIs following this. Am looking for examples from preferably common APIs of where to root our exception/error hierarchy, or comments on style or functional differences that should dictate one root in preference to the other.

+4  A: 

The rule is, don't create application exceptions that are descended from Error. The Error hierarchy is intended to be used only for non-recoverable errors reported by the JVM and core libraries.

I know of no major APIs that break this rule.

Stephen C
I didn't see any APIs either, though AssertionException seems to break that mold, especially since http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/guide/lang/assert.html advocates throw new AssertionException() as a reasonable idiom
jayshao
+3  A: 

You want to extend RuntimeException.

In general though... It sounds like the real problem is that your organization thought it better to just throw ApplicationException everywhere rather than throw specific, meaningful, well documented exceptions.

From the literature you referenced:

Contingency
An expected condition demanding an alternative response from a method that can be expressed in terms of the method's intended purpose. The caller of the method expects these kinds of conditions and has a strategy for coping with them.

Fault
An unplanned condition that prevents a method from achieving its intended purpose that cannot be described without reference to the method's internal implementation.

A single approach like "everything is unchecked" is as bad as "everything is checked" (in my opinion, worse). Apply the same conventions set by Java:
If the condition is a programming error, then it is a RuntimeException.
If the condition is something meaningful that a caller might expect and be capable of handling, use Exception.
If the condition is a system error (like unavailability of a resource), that prevents any meaningful action from proceeding, use Error(but this is very rare).

Tim Bender
To clarify - the *thrown* exceptions are part of a meaningful hierarchy. Error handling code is the code that tends to get into long chaines catching, or throwing the parent ApplicationException class
jayshao
Also, this question isn't advocating "everything is" anything, however most of our application exceptions (> 90%) seem not to fall in the category of "caller might expect and be capable of handling". Interestingly enough, for us, unavailability of a resource is often designed in, and we are attempting to operate normally with progressively less functionality.
jayshao
+1  A: 

In addition to the other answers: You should not catch Error or Throwable without rethrowing in "normal" program logic. The main reason I can think of for catching a subclass of Error is this: You are using your own class loading system and want to isolate broken plugins.

The JavaDoc for ThreadDeath says:

An application should catch instances of this class only if it must clean up after being terminated asynchronously. If ThreadDeath is caught by a method, it is important that it be rethrown so that the thread actually dies.

nhnb