3
votes

I have two related issues regarding spring/AspectJ AOP. I have a typical logger aspect which logs exceptions thrown from any class in my application including services, daos, controllers and webflow actions...

@Aspect
public class AspectLogger {

    @AfterThrowing(pointcut = "execution(* com.myapp..*.*(..))", throwing = "t")
    public void logGustavoException(JoinPoint joinPoint, Throwable t) {

        Log logger = LogFactory.getLog(joinPoint.getTarget().getClass());
        logger.error(t.getMessage(), t);
    }
}

In my application context I have an equally typical configuration...

<context:annotation-config />

<!-- AOP logging config --> 
<aop:aspectj-autoproxy>
    <aop:include name="aspectLogger" />
</aop:aspectj-autoproxy>

<bean id="aspectLogger" class="com.myapp.AspectLogger" />

This works fine for the most part, the issue I have is with the webflow actions and controllers which implement an interface.

1 - Controllers which implement an Interface...

One of our controllers implements an interface which defines one method, as well as defining several public methods which are used as @RequestMapping handlers...

@Controller
public class AmazingController implements OutstandingInterface {

    // implements the method from OutstandingInterface
    @Override
    public Object doSomethingOutstanding(){
        ...
    }

    @RequestMapping(value="/amazingUrl.htm", method = RequestMethod.GET)
    public String doSomethingAmazing(HttpSession session, ModelMap model) {
        return "anAmazingViewName";
    }

    ...
}

The issue here is that due to the fact that the controller implements an interface that doesn't define all its public methods (i.e. controller request mapping methods), a proxy is created for the controller which only proxies the 'doSomethingOutstanding' method from OutstandingInterface. As such, when a request comes in to /amazingUrl.htm, Spring does not route it to the appropriate request handler - it's as though the request mapping doesn't exist. I have solved this by defining an interface for the controller which extends OutstandingInterface and also defines the request handler methods required by the controller, but it seems odd/wrong to me to have to define an interface for a controller just so that the AspectJ stuff doesn't 'hide' the request handler...

@Controller
public interface IAmazingController extends OutstandingInterface{

    @RequestMapping(value="/amazingUrl.htm", method = RequestMethod.GET)
    public String doSomethingAmazing(HttpSession session, ModelMap model);

}

...

public class AmazingController implements IAmazingController {

    @Override
    public Object doSomethingOutstanding(){
        ...
    }

    @Override
    @RequestMapping(value="/amazingUrl.htm", method = RequestMethod.GET)
    public String doSomethingAmazing(HttpSession session, ModelMap model) {
        return "anAmazingViewName";
    }

    ...
}

2 - Webflow Actions

The second issue is very similar. After introducing the AspectJ configuration, none of my webflow Action classes were being autowired correctly - I kept getting 'cannot find bean of type FantasticAction' sort of errors. Again, I introduced interfaces for all of the Action classes and this solved the problem as it was the proxy that was being injected at runtime, not the actual action implementation class.

So finally... the question in both instances is - is there a way of getting around these AspectJ issues without having to define interfaces for every class I want to advise?

1

1 Answers

1
votes

You should add CGLIB dependendy in your class path so you will not need to create interfaces for working with AOP

Take a look to the doc.