This exception is probably one of the most common home-made exceptions, one that pops up in almost every project. I’ll try and show you how it works and what the advantages are.
One of the “problems” of doing all the business logic in the Service (or UseCase, Business) Layer is getting the right exception message back onto the screen. Lot’s of times people invent all kinds of home-brewed exceptions: e.g. ResultNotFoundException, InsufficientFundsException, DateTooFarIntoFutureException, …
Another approach, which is far worse, is to let specialized exceptions like a ConstraintViolation (hibernate), UserException (axis) and many others. It couples the front-end to back end.
When defining custom exceptions for every problem, you force the controller to catch all the exceptions that could be thrown separately. Adding a new exception can be cumbersome, and it does not really matter if you define them as checked or unchecked, unless you plan to catch the remaining exceptions with a generic info message like: something went wrong…
What’s the correct solution?
Here comes the BusinessException
public class BusinessException
extends RuntimeException {
/** A code indicating the cause of
the exception. */
private String code;
/** The exception that is wrapped by
the business component. */
private Exception wrappedException;
/**
* Constructor.
*
* @param code The code indicating the
* cause of the exception.
* @param wrappedException The exception
* that is wrapped by the business
* component.
*/
public BusinessException(String code,
Exception wrappedException) {
this.code = code;
this.wrappedException =
wrappedException;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Exception getWrappedException() {
return wrappedException;
}
public void setWrappedException(
Exception wrappedException) {
this.wrappedException = wrappedException;
}
}
When a business rule validation has been detected, a new BusinessException should be throw.
When an exception is thrown from any layer beneath the Controller layer, it should be wrapped by the BusinessException.
The code is the key for translation by the view renderer.
Placing this in the architecture
When we place the BusinessException into a widely use architectural stack we come up with something like this:

Advantages
The advantages are clear:
- The controller and other layers are loosely coupled (e.g. no DAO dependency in Controller)
- The transaction can be rolled back, since the exception is thrown.
- The controllers aren’t forced to catch many exceptions.
- No need for those custom made exceptions. One exception to rule them all!
BusinessException versus other exceptions
The businessException should wrap a recoverable violation or exception, that can be displayed in the screen. Transaction is rolled back, and the user can change the input and/or try again.
Normal exceptions are unrecoverable. The transaction is rolled back, and the user is directed to an error page.
It’s not the point to wrap every exception, but only the expected ones. Don’t wrap a It’s a really simple pattern, but a very powerful one.
In essence 4 scenario’s can happen:
- The first level fails. Typically this is something like a missing required field. The user is redirected to the same page to fix the problem.
- The second validation fails: a business exception is thrown. Typically this is a business rule that failed, for instance a balance is too low to complete a purchase. It also could be an exception wrapped by the BusinessException. For instance when the database row has changed after you loaded it.
- Everything succeeded, the business layer returned normally.
- The business layer threw an exception (not a BusinessException), the page is redirected to the error page. Unrecoverable, should only be on programming bug.
Conclusion
A lot has to be said for straight and simple win-win patterns. This one is definately one of those.