Over a million developers have joined DZone.
Platinum Partner

What's the Best Way to Handle Exceptions?

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

It seems, given my limited experience, that handling exceptions depends entirely on the context in which you are developing. As a fan of "rules" that can be applied to different scenarios I wanted to hit you guys up and see what the rules-of-thumb were with regards to exception handling.

Some approaches to exception handling sort of speak for them self, for example, swallowing exceptions in an API is always wrong, you aren't giving the caller/implementor an opportunity to handle the exception and possibly implement some intelligent work around:

try {
// open a network connection
// download a file
} catch(Exception e) {
// catch everything and just eat it

but I could think of some scenarios (especially with regards to user-interfaces) where swallowing an exception and doing nothing with it is a perfectly valid case.

Then there is the whole Checked vs Unchecked exception issue.

As an API author the idea of Checked exceptions appeals to my technical side; if I'm writing code that could do something bad, I should force the implementor to respond to that by making them try-catch my code... I'll leave it up to them to decide if they do something smart with it or not.

Unfortunately, the reality is that working with an API that uses nothing but checked exceptions is really frustrating (e.g. early versions of Hibernate) and cause your code to start looking overly complex. You might make some short-cuts by just marking your own methods as throwing those exceptions or throwing massive blocks of code into try-catch blocks just not to be bothered by it. The frustration can even be compounded when the code you are using almost always runs without a problem... you begin to doubt the need for good try-catch block semantics.

To work around this, when developing APIs, I've started re-throwing exceptions as Unchecked RuntimeExceptions, which my technical side hates, but my "I'm a real person and have things to get done" side likes, it lets the dev respond to potential exceptions (albeit a bit more generic) if they want to, otherwise they can ignore it:

try {
// do something that can throw an exception
} catch(Exception e) {
// catch all exceptions
throw new RuntimeException("<some detailed description of what barfed>", e);

The idea being that by-way of the human-readable message and the wrapped exception, the caller and developer, should have enough useful information to figure out what went south.

Now with regards to application development, I find myself simply logging and eating exceptions all over the place, something along the lines of:

try {
// do something error-ey
} catch(Exception e) {
logger.log("<some message that will help me later>", e);
// do nothing else

In some cases when I want my app to die due to an exception (or at least throw it back up a level) I'll re-throw the exception, but that seems to be few and far between for the most part.

It's these erratic treatments of exceptions that pushed me to finally write this all down and ask the community what they do as real developers, not as text-book writers where best-practices are always employed no matter what.

Specifically, the following scenarios:

  • As an application author, how do you catch/handle/log exceptions that occur that are non-critical? (obviously critical exceptions have to be handled, but what about the rest?)
  • As an API author, do you use Checked or Unchecked exceptions?
  • As an API author, do you rethrow exceptions or swallow them in hopes of making the API easier for the implementor?
Looking forward to feedback, suggestions, rants or just cat pictures with funny captions.

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}