Comments on Microsoft Enterprise Library Exception Block
We have been using the “Microsoft Enterprise Library Exception Block” for exception handling and logging in the current Enterprise Information management Systems that I am working on. Based on my experience with the “Microsoft Enterprise Library Exception Block“, I had a couple of comments that wanted to put out there. These observations of mine may just be complaints about the library that I wish could have been circumvented. But I do agree that the library does provide us with a powerful tool to standardize the way exceptions are handled throughout the application. For those who haven’t used the Exception block library before, here is a quick overview. I feel that this is a great one line summary of the Exception block. “The Exception block separates the definition how an exception should be processed from the application code itself“.
Exception Handling Application Block
It is a framework for handling exceptions (catching, presentation to the user, logging, etc.) in a recommended and standardized way. It allows developers and policy makers to create a consistent strategy for processing exceptions that occur throughout the architectural layers of enterprise applications. It does this in the following ways:
- It supports exception handling throughout an application’s architectural layers and is not limited to service interface boundaries.
- It enables exception-handling policies to be defined and maintained at the administrative level so that policy makers, who may be system administrators as well as developers, can define how to handle exceptions. They can maintain and modify the sets of rules that govern exception handling without changing the application block’s code.
- It provides commonly used exception-handling functions, such as the ability to log exception information, the ability to hide sensitive information by replacing the original exception with another exception, and the ability to add contextual information to an exception by wrapping the original exception inside of another exception. These functions are encapsulated in .NET classes called exception handlers.
- It can combine exception handlers to produce the desired response to an exception, such as logging exception information followed by replacing the original exception with another.
- It lets developers create their own exception handlers.
- It invokes exception handlers in a consistent manner. This means that the handlers can be used in multiple places within and across applications.“
The Exception block separates the definition of how an exception should be processed from the application code itself and moves this configuration to a XML config file. The configuration of the Exception block uses following terms:
A Policy has a name and a set of exception types that should be processed. An application can have several policies, because it could be necessary to have different processing instructions for one exception type, depending in which layer of the application the exception arises.
For each policy one or more exception types can be defined. Exception types can be one of the standard .net exception classes or user defined ones. When an exception is thrown the exception block will determine the type of the exception against the definitions in the used policy and call the exception handlers of this type.
Exception handlers process the exception. An exception type can have one or more handlers. They are called by the application block in the order like they were configurated.
There are following built-in handlers:
- Wrap handler: Creates a new exception and sets the original exception as inner exception for the new one.
- Replace handler: Replaces an exception with a new (custom) one.
- Logging handler: Logs the exception to the Enterprise application logging block, which can be used to log events to different targets like event log, files, databases etc.
- Custom handlers: Developers can write their own exception handlers which can be easily included in the project (see “Creating a custom exception handler”.
The following figure illustrates examples of cross-layer and single-application component exception handling:
The figure above shows how the “UI Layer (UI)”, “Business Components Layer (BCL)” and the “Data Access Layer (DAL)” normally handle exceptions. Any exceptions that occur in the DAL library should be logged and then wrapped with some meaningful contextual information on where and possibly why the exception happened and passed up to the calling BCL library. The BCL library handles the exception by logging it and if necessary replacing it with an another exception that makes more sense when finally handled by the UI layer and displayed to the user.
The policy that should handle the exception is specified by the developer in the ExceptionPolicy.HandleException(…) method as shown below.
catch (Exception e)
bool rethrow = ExceptionPolicy.HandleException(e, “exception policy name”);
Ideally, I think that there should be some kind of restrictions on the type of policies that can be specified in the parameter for the ExceptionPolicy.HandleException(…) method. By that I mean, for example the “Notify User” policy should never be used in the DAL or the BCL.
My other comment about the above code is that, the developer is now responsible for handling the “rethrow” boolean value returned by the ExceptionPolicy.HandleException(…) method and explicitly throwing the exception again. The rule to throw exception again is not encapsulated in the policy itself. Also, the decision to throw the exception again is based on the exception that has occurred. Some exceptions may need to be thrown again but some others need not. Given that most programmers are lazy, there is a real good chance that the exceptions do not thrown again. This can lead to situations where exceptions get swallowed without proper user notification if required. The kind of errors can be hard to track down because there may not be a user notification that some thing has gone wrong and can cause problems in parts of the system that rely on it. Maybe some custom FxCop rules can be checked to catch these errors before they move into production.