Centralized exception handling and logging using Spring.NET
4/19/2009
This is a quick tutorial to implement a .NET application/service facade with exception handling, without writing unnecessary, repeated try/catch blocks and logging mechanism. For more details and goals, please read my article about Centralized exception handling and logging in .NET by AOP.
In this article I show you a step-by-step centralized exception handling and logging tutorial with Spring.NET, next week I submit a post about how to do the same with PostSharp.
The first step, isn't a surprise, you have to download Spring.NET Framework.
It's time to open Visual Studio 2008. You can use 2005 as well, but my sample code can be opened by 2008.
I created a C# class library project (CodeRecycling.ServiceFacade) for my code and a test project (CodeRecycling.ServiceTest) for my unit tests.
Spring.NET has a lot of features, we will use only the Aspect-oriented module, so in CodeRecycling.ServiceFacade project we add a reference to Spring.Aop.dll.
I added a new class called SpringHandledFacade, imagine this contains all the methods called by client applications. As it is only a facade, it calls the lower layers. I added the BusinessLogic class for this reason.
The BusinessLogic implements the IBusinessLogic interface. This interface is necessary because of the Dependency Injection. I use the Dependency Injection Pattern to avoid writing real business logic implementation and make the application more testable (I will inject a fake business logic here later). The interface has one method: GetNecessaryData() - has no meaning, but will be perfect for us (in the other hand this a tribute to Molino, my ex-colleague).
Let's go to the test project:
SpringHandledFacadeTest will contain the unit tests to perform assertions on the facade.
I added an other class called DummyBusinessLogic, I will use this as a test double.
We haven't done any error logging or exception handling, we don't use Spring.NET by the moment. I will apply the test-driven approach and specify our requirement by this unit test.
So we set the fake BL to the facade (which throws a NotImplementedException), and we expect a custom MyServiceExpcetion type. It's an exception-handling principle to wrap unhandled exceptions to a custom type.
You return more detailed or more generic exception in your custom exception type (this depends on your service consumers and your needs), I just inherited from ApplicationException and used a simple constuctor chaining.
After implementing your own Exception type, the project will be still unable to be compiled, because you don't have the constructor of the facede and the facade lacks of the GetNecessaryData() implementation.
After adding your code to the facade class, you can compile, but your unit test will be red. No problem this was our goal. Remember the TDD mantra: Red-Green-Refactor.
The next step is to generate a proxy for Spring.NET and attach the exception handling to it. I coudn't find a good solution to check exceptions directly in the facade, so I generaty a proxy for my BL, because the facade only calls the BL. In the other hand, I was able to define the advice directly to the facade by using PostSharp (will be discussed in the next post).
Don't forget to include the Spring.Aop.Framework namespace.
Normally the flexibility of Spring.NET is very benefitial: you can use the IoC module and inject the advice using the configuration file. In the first version, I did the same, but I realized that I don't want to change the configuration, I don't want to replace the error handling logic. The exception handling should work without configuration file, bacause inproper/missing configuration can cause exceptions. So I decided to avoid using the IoC modul of Spring.NET for logging.
Now you can't compile, because you don't have the SpringErrorHandlerAttribute class. In turn this is the heart of the logging and exception handling.
The following diagram shows the utilized AOP framework classes associated to the different facades.
So let's add a new class and use the Spring.Aop namespace!
Compile, run the test! GREEN! Grats, you can log all the exceptions from the business logic, you can wrap and rethrow them to the client applications as you wish.
We have clear code, without unwanted try-catch blocks in each method. It's nice, elegant, Object-Oriented and easy to maintain.
Furthermore you have have the method and args parameters, so you can log these important information.
You can download all the code examples from here.

0 comments:
Post a Comment