Best practices on Exception handling

This guide is designed with the idea of providing a basis for the management of Exceptions in general by the use of Blunder or outside it. Humbly, the aim is to promote good practices in the handling of errors within each application. As in all cases, there are always exceptions to the rules, these require further analysis from the developer.

Each case is a special situation that will try to generalize some examples. However, this guide is not exhaustive, and is always appealing to the wisdom of each developer for resolving the cases failed to be covered here.


Case 1: Do not catch, log and re-throw

This is a bad practice because if the Exception is being re-thrown, in any other layer of the application there is some code catching and logging it again. The resulting behavior is the successive logging of the same error, and consequent contamination of the log. One Exception should be logger just once.

try {
 
// Something risky...
} catch ( Exception e ) {
 
log.error( "We got an error: " + e.getMessage(), e );
 
throw e;
}


Case 2: Catch and throw new

In the cases we're catching an error and throwing another is always advisable chaining the original error. This allows, at the time of the analysis, a greater level of detail and prevents the loss of the original Exception.

try {
 
// Something risky...
} catch ( Exception e ) {
 
// Always chaining with the original
 
throw new Exception( "We got an error", e );
}


Case 3: Exception.printStackTrace()

In the cases where we have available a logging api, it is highly recommended to use it and not use the printStackTrace() method. By default, this method prints the stacktrace in the System.err, and that could not be reflected in the log file.

try {
 
// Something risky...
} catch ( Exception e ) {
 
// Only if we don't have a logging api
 
e.printStackTrace();
}


Case 4: Avoid catching of java.lang.Throwable

The catch by Throwable also handles system errors, those who inherit from java.lang.Error, and generally can not be handled or recovered. So there is no point in trying to catch them.



Case 5: Unnecessary particularization

In this particular case, we have more than one catch block doing the same thing. The most appropriate in this case would be to use a single block where all Exceptions are caught as we are not discriminating between one or the other. The rule is not particularize or generalize if not necessary.

try {
 
// Something risky...
} catch ( IOException ioe ) {
 
log.error( "Ups! mistakes happen...", ioe );
} catch ( SQLException sqle ) {
 
log.error( "Ups! mistakes happen...", sqle );
} catch ( Exception e ) {
 
log.error( "Ups! mistakes happen...", e );
}


Case 6: Throw of java.lang.Exception

The throw of new java.lang.Exception objects, should be limited. It's a good practice to make your own Exception class (add some value on it) and throw it instead always chaining where is possible.



This page contains Java code formatted with http://www.java2html.de.