Exceptions for action

Exception design for efficient error handling

1 2 3 4 Page 3
Page 3 of 4

Sample exception set

In Figure 1 you see four kinds of exceptions designed to take four kinds of action, as follows:

  1. BusinessException: An exceptional condition has occurred. This condition was foreseen and can be checked by the calling method for immediate action.
  2. ParameterException: The data entered does not allow for proper processing. The user must be asked to re-enter valid data or to modify the conditions in which processing occurs.
  3. TechnicalException: A technical issue like an invalid SQL statement has occurred. The requested operation cannot be fulfilled. The user should contact the help desk for investigation or try another service. The use of the application by other users is not impacted.
  4. CriticalTechnicalException: A technical issue like a database crash has occurred. In these conditions, the whole application is unusable. The user should be encouraged to retry later. Other users should not use the application until it has been repaired.

This set of exceptions is only one example; many other exception sets could be defined similarly. For example, TechnicalException and CriticalTechnicalException could be designed as a single exception class with a boolean severity attribute. What is important is to focus on the kind of action that should be taken, rather than on the issue that raised the exception.

Exception logging

Although the exception semantics focus on the action to take, the issue that has been raised is also important. The development team could, for example, use this information to debug the code. In my exception design, information about the cause of the exception can be found in the application's error log file. With a good logging framework in place, it should be sufficient to log information about the issue from the exception message and stack trace.

The only issue that remains in how to design the exception so that this information can be easily retrieved. One solution is to provide the exception with an id attribute representing the kind of issue at hand. Also, if the issue has thrown its own exception, this exception can be nested into the application exception. At catching time, the original message and stack trace can be retrieved from the nested exception. The id attribute and exception nesting are two ways to include issue-related information in the exception itself.

Designing the flow of exceptions

Once you have designed the exceptions themselves, the next step is to think about how they will flow through your application. A standard JEE application architecture is mainly composed of four packages: presentation, business, integration, and persistence. Exceptions are typically thrown by the integration and persistence packages. In the business package, the inner runtime layers catch checked exceptions as soon as they can, while the outer layers catch the runtime exceptions and take appropriate actions according to their class. You can also throw and catch some checked exceptions inside the business package. In this scheme, the responsibility of the integration and persistence packages, as well as of the business package's inner layer, is to convert runtime exceptions into actions. A typical JEE application architecture of this sort is shown in Figure 2.

Exception flow in a standard JEE package architecture.
Figure 2. Exception flow in a standard JEE package architecture (click for a larger image)

The path of an exception thrown from the persistence package (for example) depends on where the issue can be resolved. If the calling method can resolve the issue, the exception is caught immediately, the appropriate action is taken, and the business flows on normally. If the issue cannot be resolved, the exception is nested into a runtime exception and passed on silently through the business package's intermediate layers into to the upper layers of the application. In these layers, typically by some kind of application controller, the runtime exception is caught, the appropriate action is taken, and the presentation layer displays the corresponding error message to the user. Immediate catching of checked exceptions and late catching of runtime exceptions are the two main scenarios in this kind of exception design, as shown in Figure 3.

Immediate catching of a checked exception and late catching of a runtime exception.
Figure 3. Immediate catching of a checked exception and late catching of a runtime exception (click for a larger image)
1 2 3 4 Page 3
Page 3 of 4