Anyone who has programmed with Java should be familiar with the concept of Checked Exceptions. Although C++ and OCaml have optional support for exception checking, Java seems to be the only major programing language where it is a built-in and required part of the language. Enforcing at compile time that certain exceptions need to be caught may have seemed like a good idea at the time Java was developed, however no major languages developed since have adapted the concept. Many view Checked Exceptions as a design flaw. In this article, I attempt to show how this flaw can be overcome using a base exception class to encapsulate exception handling.

Many of the libraries in java tend to throw a lot of different exceptions, especially when dealing with any type of Input/Output either on the disk or via network. Take the following example in which the sendMail function uses the JavaMail API in order to send a message:

try {
    sendMail(from,to,subject,body);
}
catch(AddressException e) {
    //Handle This Exception 
}
catch(UnknownHostException e) {
    //Handle This Exception
}
catch(MessagingException e) {
    //Handle This Exception
}

In some projects I would often catch the base exception class and use the instanceof keyword to clean up the exception handling as seen below. Although the code for this technique may be cleaner, it’s more difficult to add new exception types that may be introduced later by code changes:

String error = "";
try {
    sendMail(from,to,subject,body);
}
catch(Exception x) {

    error = "Internal Error: ";

    if(x instanceof AddressException) {
            error += "Invalid Internal Address";
    }
    else if(x instanceof UnknownHostException) {
            error += "Could Not Find Mail Server";
    }
    else if(x instanceof MessagingException) {
            error += "Messaging Problem";
    }
    else {
           error += "Unexpected: " + x.getMesssage();
    }
}

In both instances, programmers typically just log the exception and display a general error to the end user. Catching the individual exception types doesn’t really help in any meaningful way. Also, the exception message itself is often human readable and a clear indication of what error occurred. In my current projects, I use a base exception class and simply place any code that produces checked exceptions within a large try block and rethrow any exceptions as a property of my base exception class.

public class SimpleException extends Exception {

	private Throwable nestedException;
	
	public SimpleException(String s) {
		super(s);
	}
	
	public SimpleException(String s, Exception nestedException) {
		super(s);
		this.nestedException = nestedException;		
	}
	
	public Throwable getNestedException() {
		return this.nestedException;
	}
	
} 

Using this class, the previous example would change to the following:

String error = "";
try {
    sendMail(from,to,subject,body);
}
catch(Exception e) {
    throw new SimpleException("Error Occurred Sending E-mail",e);
}

This cleans up our code significantly. Under the old model, say that the implementation changed and new potential exceptions could possibly be thrown. Each one of those exceptions would have to be added to the throws clause to the appropriate function. If the class implemented a interface or extended and abstract class, those base methods would have to change as well, along with any code implementing the class. If we throw only one type of exception that wraps all other exceptions, we never have to worry about the method signature changing.

Some programmers may oppose this approach and classify it as an anti-pattern, similar to wrapping all checked exceptions in blocks that rethrow runtime exceptions. However, in my experience in working with large projects, using this approach is much cleaner and more maintainable. Furthermore, it allows Aspect Orientated Programming (AOP) interceptors to have a lot more information when dealing with exceptions.

This article is the first in a series of tutorials on J2EE development. The use of the except pattern I’ve used will be further expanded with seeing how it can integrate into web applications using Spring and AOP.