Skip to main content

Spring.NET exception handling through AOP

Spring has few custom handlers that help application developers with exception handling. Recently, on one of the projects I was working on I had a requirement where I was to log user exception, capture the exception detail, and email the exception details to a set up email address.

The first thing I looked at was Spring.Net's ExceptionHandlerAdvice in Spring.Aspects.Exceptions namespace. You can use this predefined advice to handle your exceptions. You can take a look at chapter 14 of Spring.NET documentation to get more details about what this advice does for you.

Looking at ExceptionHandlerAdvice, I knew that I had to set up the exceptionHandlers property. I used the following value to set this property.

on exception (#e is T(System.Exception)) execute @(customExceptionHandlingAdvice).Handle(#e)

The above value using Spring.NET SPeL (Expression Language). You can find out more about the Spring's expression language in the Spring.NET documentation.

Exception handler value above basically states that when the caught exception is type of System.Exception, execute the Handle method of customExceptionHandlingAdvice object. The customExceptionHandlingAdvice object is a Spring bean defined in the spring context. You can see that the original exception is passed into the Handle method of the object through the expression language. In customExceptionHandlingAdvice.Handle method I basically put together an email text and email it to a set up email.

As you can see, this is pretty straight forward to set up. When you set this up and test it, it will all work with the exception that the original "exception" will not be re-thrown after it was caught. This was a big problem for me because I still wanted to make sure that the end users received the custom error page I set up in ASP.NET.

I dug into the code of ExceptionHandlerAdvice and found out that exception is not re-thrown when the action in SPeL is set to "execute" which was the case in my situation. The reason why ExceptionHandlerAdvice was not throwing the original exception was that a returned value from the ExecuteSpelExceptionHandler (handler object that is used to handle specific action -- in this case Execute) was set to null.

ExceptionHandlerAdvice is re-throwing the original exception when the return value from the specific action exception handler is set to "logged" (for action log), "nomatch" for (not finding any specific handler).

After realizing that was the case, I had few options to extend Spring.NET's behavior. I either could provide my own custom ExceptionHandlerAdvice or my own custom ExecuteSpelExceptionHandler. I picked the latter approach because I was also logging the exception in the Handle method of my customExceptionHandlingAdvice bean.

I created an object called CustomExecuteSpelExceptionHandler that extended ExecuteSpelExceptionHandler and overrode HandleException method. In the HandleException method I made sure that I was returning "logged" instead of "null". This allowed ExceptionHandlerAdvice to re-throw the exception after it was logged and emailed in my Hanlde method.

Needless to say I had to register my CustomExecuteSpelExceptionHandler with ExceptionHanlderAdvice. I was able to do this using exceptionHandlerDictionary property of the ExceptionHandlerAdvice object.

Here is how my Spring.NET configuration looks.

<object id="customExceptionHandlingAdvice" name="customExceptionHandlingAdvice" type="App.Utils.Aop.ExceptionHandlingAdvice"/>

  <object id="exceptionHandlingAdvice" name="exceptionHandlingAdvice" type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
    <property name="exceptionHandlers">
      <list>
        <value>on exception (#e is T(System.Exception)) execute @(customExceptionHandlingAdvice).Handle(#e)value>
      list>
    property>
    <property name="exceptionHandlerDictionary">
      <dictionary>
        <entry key="execute">
          <object id="customExecuteSpelExceptionHandler" name="customExecuteSpelExceptionHandler" type="Hcpm.Extension.CustomExecuteSpelExceptionHandler, App.Core">object>
        entry>
      dictionary>
    property>
  object>

It then becomes very easy to apply this exception advice to your data layer or your service layer.

Comments

Unknown said…
what is Hcpm.Extension.CustomExecuteSpelExceptionHandler
ismail said…
That object was used to exten ExecuteSpelExceptionHandler from Spring.NET.

ExecuteSpelExceptionHandler was catching exception and logging it. I needed it to still return the exception so that in my use case after I sent the e-mail exception was re-thrown so end users would see a custom error page. You can take a look at the source code of it here.

http://www.java2s.com/Open-Source/CSharp/Inversion-of-Control-Dependency-Injection/Spring.net/Spring/Aspects/Exceptions/ExecuteSpelExceptionHandler.cs.htm

Hope this helps.