Search code examples
javaspringtomcatspring-aop

Spring AOP not working in web-application on tomcat 8


I want to use Spring AOP for some logging stuff in my application. I used AOP already in a standalone application and it worked but now with a web-app on a tomcat it's not working.

I have a application-core and a application-web project, where in the core project all the logic happens and the web-project contains only the web-related stuff.

First I tried to add my LoggingAspect class inside my core project, as this did not work I moved it now to the web project but although there it does not work.

Here is my applicationContext.xml which is in folder: /application-web/src/main/webapp

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">

        <!-- Add AspectJ autoproxy support for AOP -->
        <aop:aspectj-autoproxy/>


        <!-- Step 3: Add support for component scanning -->
        <context:component-scan base-package="my.foobar"/>

        <!-- Step 4: Add support for conversion, formatting and validation support -->
        <mvc:annotation-driven/>

        <!-- Step 5: Define Spring MVC view resolver -->
        <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/view/" />
            <property name="suffix" value=".jsp" />
        </bean>
    </beans>

And This is my LoggingAspect class which is now here located: application-web/src/main/my.foobar.web/aspects/LoggingAspect

    @Aspect
    @Order(1)
    public class LoggingAspect {
        private static final LogHandler LOG = LogHandler.getLogger(LoggingAspect.class);

        @Pointcut("execution(* my.foobar.*.*.*(..))")
        private void completePackage(){}

        @Pointcut("execution(* my.foobar.*.*.get*(..))")
        private void getterMethods(){}

        @Pointcut("execution(* my.foobar.*.*.set*(..))")
        private void setterMethods(){}

        @Pointcut("completePackage() && !(getterMethods() || setterMethods())")
        private void allMethodsExceptGetterAndSetter(){}

        @Around("completePackage()")
        private Object aroundMethod(ProceedingJoinPoint theProceedingJointPoint) throws Throwable{
            LOG.info("around method");
            String method = theProceedingJointPoint.getSignature().getName();
            Object[] arguments = theProceedingJointPoint.getArgs();

            LOG.info("method call: {0}", method);                
            for(Object arg: arguments){
                LOG.info("argument[{0}]", arg);
            }

            Object result = theProceedingJointPoint.proceed();
            return result;
        }

    }

I have also added a class to my application-web project

@Configurable
@EnableAspectJAutoProxy
@ComponentScan("my.foobar")
public class ApplicationWebAppConfig {

}

What I expect is, that each method which is called will be logged but thats not happen.


Solution

  • Al Phaba wrote:

    I think I figured out my problem. I thought I could use just spring-aop as a standalone feature in my application. I was adding some JSP pages and used for this the first time spring-mvc and during this I saw spring-aop and thought why not using this for some additional measurements of my methods. My sample standalone application worked really good thats why i tried to adapt this to my existing application. But here the problem starts, the methods which I want to measure are not spring related so as posted from kriegaex here this is not working.

    Yes, Spring relies on dynamic proxies (by default JDK proxies for classes implementing interfaces, CGLIB proxies for classes not implementing interfaces), and these proxies only work on Spring components because only those get proxied by Spring while wiring the application. AspectJ however weaves directly into the original class's bytecode and can be applied to non-Spring classes as well, as long as they are not already loaded when AspectJ is activated (e.g. JRE classes).

    My solution is a bit disappointing I stopping my feature branch at this point because it currently to much effort to solve it, as I read and you answer suggest I need to switch to AspectJ via LTW.

    Well, if your application is working already, if you do it right it is a matter of minutes to change the configuration from Spring AOP to AspectJ as described in the Spring manual. I am encouraging you to give it a try, it is really not that hard. Good luck.