Used to indicate that some part of a multi-step process failed. Typically,
operation can continue after this exception is caught.
Before throwing an object of this type, the thrower
- must log a detailed user-facing message describing the failure,
- must report any caught exception using the logger that contributed to
the failure, and
- must not include the cause of the failure in the thrown exception
because (1) it will already have been associated with the detailed log entry
above and (2) doing so would create a misunderstanding of how to find the
causes of low-level errors in that sometimes there is an underlying an
exception, sometimes not, but there can always be a preceding log
entry.
After catching an object of this type, the catcher
- can be assured that the thrower has already logged a message about the
lower-level problem
- can optionally itself log a higher-level description of the process that
was interrupted and the implications of the failure, and if so,
- should report this caught exception via the logger as well.
void lowLevel(Logger logger) throws UnableToCompleteException {
try {
doSomethingThatMightFail();
catch (SomeException e) {
// Log low-level detail and the caught exception.
//
logger.log("detailed problem explanation for user eyes...", e);
// Do not include the caught exception.
//
throw new UnableToCompleteException();
}
}
void highLevel(Logger logger) {
try {
// Multiple calls are shown to indicate that the process can
// include any number of steps.
//
lowLevel(logger);
lowLevel(logger);
lowLevel(logger);
}
catch (UnableToCompleteException e) {
logger.log("high-level thing failed", e);
}
}