Spring’s AOP support can’t be ignored

You see I’ve never actually written many (any?) AOP classes but there’s enough talk about it splashed all over the internet that even though it might be a worthless concept that you’ve never used or cared about, you’re bound to encounter it at some point. A fellow GO Train rider once told me it was the thing to know if you want to have a Java job in five years. That made me read the AspectJ in Action book which makes you feel guilty about not using AOP. I don’t talk to that guy anymore. Then there’s Adrian Colyer who will have you believe that AOP is the glue that ties every enterprise application together and without it you might be writing code that is hanging on by threads.

Now I realize for some of you this might bring flashbacks to 2004 but bear with me. A few days ago I had to catch an Exception in the DAO layer and translate it to something else, now normally this very simple problem is solved by 95% of the monkeys by using a try/catch on the Exception and throwing something more worthy of being bubbled up. But if the same DAO method is being executed in different places in your application you might have to do separate try/catch blocks for each, something which is totally acceptable, clear, concise and happening for ages. There’s nothing wrong with it.

But there is an AOP way of doing this outlined pretty clearly in the docs where you write a pointcut and provide advice on the execution of the event. No try/catch blocks, the client code is devoid of any knowledge about exceptions. Spring’s AOP support makes doing this the AOP way very easy, but is it overkill? I don’t know, I guess it depends on your style of development.

So to replace the generic try/catch mechanism with the AOP way, first declare a pointcut:

package com.arsenalist.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SystemArchitecture {

    @Pointcut("execution(* com.arsenalist.dao.*.*(..))")
    public void daoOperation() {}
}

Once we’ve specified what methods to monitor using pointcuts, give advice on what should happen when the pointcut is executed.

package com.arsenalist.aop;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class DaoExceptionTranslator {

    @AfterThrowing(
      pointcut="com.arsenalist.aop.SystemArchitecture.daoOperation()",
      throwing="ex")
    public void translateException(Exception ex) {
        throw new RuntimeException("Generic message");
    }
}

With the above setup any method executed in the com.arsenalist.dao.*.* packages will be translated into a RuntimeException. I’m assuming that the interfaces reside in com.arsenalist.dao package and the implementations in a package underneath that. Here’s the Spring configuration needed:

<bean id="daoExceptionTranslator" class="com.arsenalist.aop.DaoExceptionTranslator"/>
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

Most importanly the Maven POM should look something like this:

<dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.5.3</version>
</dependency>
<dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.5.3</version>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib-nodep</artifactId>
    <version>2.1_3</version>
</dependency>
<dependency>
    <groupId>asm</groupId>
    <artifactId>asm-all</artifactId>
    <version>2.2</version>
</dependency>

Although there is a newer version of ASM available, it doesn’t seem to be compatible with Spring AOP.

There can be many arguments against this setup, the main one being that you’re unable to handle the same Exception differently depending on where it’s being called from. To do that you’d have to specify another pointcut and another advice on how to handle it. You also lose all call-context information because you’re assuming that everthing you need to handle the exception is in the Exception object.

But in the general sense it does seem to be an improved method of executing baseline operations when a particular event occurs. The docs get you thinking about other places where you can use AOP proxies instead of the “normal” way of doing things and it’s pretty easy to get sucked into “convert everything to AOP mode”.

If you’re afraid of proxies, this is not for you. Every call to the DAO layer happens via a proxy which is necessary to achieve the intended effect. I’m not sure what the performance penalites of using proxys on every single call to the DAO layer are but if you go this route, CGLIB proxies are apparently much faster than their JDK counterparts. Either way, if you haven’t tried out AOP but are sick of hearing the sound of it, give Spring AOP a shot. It’s probably worth it.

Advertisements

3 thoughts on “Spring’s AOP support can’t be ignored

  1. Ricky Clarkson

    One alternative to AOP in the ‘exception’ case is to have your IoC framework give you a handler for exceptions.

    context.getExceptionHandler().handle(exception);

    or perhaps you need to tell the exception handler which class the exception came from:

    context.getExceptionHandler().handle(exception,TheCurrent.class);

    You could even use that to provide ‘restarts’.

    int x;

    try
    {
    x=someMethodThatMayThrowAnException();
    }
    catch (SomeException e)
    {
    x=context.getExceptionHandler().restart(e,Integer.class);
    }

    ..there, anything could happen, such as the user being prompted to supply an alternative. See the chapter on Conditions in Practical Common Lisp to see what I’m talking about.

    If the code still has duplication, then remember that you might be missing a decent macro system, rather than AOP.

    Reply
  2. Dmitry

    Your situation is an absolutely sensible and common. I run into this often at the client site. Just recently I doing an implementation of something or other and client was dictating use of a 3rd party library that was written to be run from command line and would System.exit() on any exception. So I ended up setting up an aspect with a before advice on any System.exit() call and throw a runtime exception. Now the library is usable in the app server. AOP is a very useful tool to have.

    Reply
  3. Pingback: Proxy Templates » Blog Archive » Proxys July 2, 2007 11:41 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s