Hot questions for Using AspectJ in exception

Question:

I got the following advice :-

@Before(value="@annotation(loggable)", argNames="joinPoint, loggable")
    public void before(JoinPoint joinPoint, Loggable loggable) {
        Class<? extends Object> clazz = joinPoint.getTarget().getClass();
        MethodSignature methodSignature = (MethodSignature) joinPoint
                .getSignature();
        Method method = methodSignature.getMethod();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        RequestMapping myAnnotation = method
                .getAnnotation(RequestMapping.class);
        CodeSignature codeSignature = (CodeSignature) joinPoint
                .getSignature();
        String[] argNames = codeSignature.getParameterNames();
        logger.info(".....");

    }

in Class LoggerAspect:

package net.prcins.esales.web.aspects;



import java.lang.reflect.Method;

import net.prcins.esales.aspect.IRequestLogger;
import net.prcins.esales.log.annotation.Loggable;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Aspect
public class LoggerAspect implements IRequestLogger{

    static Logger logger = LoggerFactory.getLogger("LoggerAspect");

    long startTime;

    //@Before(value = "execution(* net.prcins.esales.web.controller..*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", argNames="joinPoint, loggable")

    @Before(value="@annotation(net.prcins.esales.log.annotation.Loggable)", argNames="joinPoint, loggable")
    public void before(JoinPoint joinPoint, Loggable loggable) {
        Class<? extends Object> clazz = joinPoint.getTarget().getClass();
        MethodSignature methodSignature = (MethodSignature) joinPoint
                .getSignature();
        Method method = methodSignature.getMethod();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        RequestMapping myAnnotation = method
                .getAnnotation(RequestMapping.class);
        CodeSignature codeSignature = (CodeSignature) joinPoint
                .getSignature();
        String[] argNames = codeSignature.getParameterNames();
        logger.info(
                "Entering Method [{}] RequestMapping:[{}] QuoteInformation:[{}]",
                new Object[] {
                        methodName,
                        constructRequestMappingString(method
                                .getAnnotation(RequestMapping.class)),
                        arguments(argNames, args) });

    }


    public void afterReturning(JoinPoint joinPoint, Object returnValue) {

        Class<? extends Object> clazz = joinPoint.getTarget().getClass();
        String methodName = joinPoint.getSignature().getName();
        if (joinPoint.getSignature() instanceof MethodSignature) {

            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Class<?> returnType = signature.getReturnType();

            if ("void".equalsIgnoreCase(returnType.getName())) {
                logger.debug("  <<<==== Leaving {} " , new Object[] { methodName});
                return;
            }
        }
        long endTime = System.currentTimeMillis();
        logger.debug( " <<<==== Leaving {} in {} ms returnValue: {}", new Object[] {methodName,(startTime-endTime),constructArgumentsString(clazz, returnValue)}  );

    }


    public void afterThrowing(JoinPoint joinPoint,  Throwable throwable) {
        String methodName = joinPoint.getSignature().getName();
        logger.error(" Exception in method:"+methodName, throwable);

    }

    private String constructArgumentsString(Class<?> clazz, Object... arguments) {
        StringBuffer buffer = new StringBuffer();
        for (Object object : arguments) {
            if (object instanceof byte[]) {
                //do nothig
            }else {
                buffer.append(object);
                buffer.append(", ");
            }
        }
        return buffer.toString();
    }


    private String constructRequestMappingString(RequestMapping myAnnotation) {
        StringBuffer buffer = new StringBuffer();
        for (String requestURL : myAnnotation.value()) {
            buffer.append(requestURL);
        }
        for (RequestMethod requestMethod : myAnnotation.method()) {
            buffer.append(", ");
            buffer.append(requestMethod.name().toString());
        }
        return buffer.toString();

    }

    private String arguments(String[] argNames, Object[] arguments) {
        for (int i = 0; i < arguments.length; i++) {
            if ("model".equalsIgnoreCase(argNames[i])) {
                String modelInfo = arguments[i].toString();
                String[] tokens = modelInfo.split(", ");
                for (String token : tokens) {
                    if (token.startsWith("quoteNumber")) {
                        return token;
                    }
                }

            }

        }
        return "";
    }

}

and this Annotation:

package net.prcins.esales.log.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import net.prcins.esales.log.LogLevel;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {

    LogLevel value();
}

Stack Trace :

SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageSource' defined in ServletContext resource [/WEB-INF/config/spring/esales-web-context.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.config.internalCacheAdvisor': Cannot resolve reference to bean 'org.springframework.cache.annotation.AnnotationCacheOperationSource#0' while setting bean property 'cacheOperationSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.annotation.AnnotationCacheOperationSource#0': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.initMessageSource(AbstractApplicationContext.java:779)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:460)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
    at javax.servlet.GenericServlet.init(GenericServlet.java:160)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:650)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1582)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.config.internalCacheAdvisor': Cannot resolve reference to bean 'org.springframework.cache.annotation.AnnotationCacheOperationSource#0' while setting bean property 'cacheOperationSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.annotation.AnnotationCacheOperationSource#0': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:86)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:100)
    at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:84)
    at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:107)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:278)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:880)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:852)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)
    ... 30 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.annotation.AnnotationCacheOperationSource#0': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
    ... 47 more
Caused by: java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:193)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:182)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:163)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:210)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:264)
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:296)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    ... 53 more
Sep 9, 2014 11:13:11 AM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /esales-ui-web threw load() exception
java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:193)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:182)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:163)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:210)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:264)
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:296)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(BeanFactoryAdvisorRetrievalHelper.java:86)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(AbstractAdvisorAutoProxyCreator.java:100)
    at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:84)
    at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:107)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:278)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:880)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:852)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.initMessageSource(AbstractApplicationContext.java:779)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:460)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
    at javax.servlet.GenericServlet.init(GenericServlet.java:160)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:650)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1582)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor C:\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\conf\Catalina\localhost\MylesERemindersEnterprise.xml
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.SetContextPropertiesRule begin
WARNING: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:MylesERemindersEnterprise' did not find a matching property.
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor C:\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\conf\Catalina\localhost\MylesERemindersWeb.xml
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.SetContextPropertiesRule begin
WARNING: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:MylesERemindersWeb' did not find a matching property.
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\webapps\manager
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\webapps\ROOT
Sep 9, 2014 11:13:11 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Sep 9, 2014 11:13:11 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 9413 ms

I get the error:java.lang.IllegalArgumentException: error Type referred to is not an annotation type: loggable

Why is Loggable no Annotation? It is marked with @interface


Answer:

I resolved the issue by refreshing and updating the dependencies. Somewhere it was not referring to the correct Loggable annotation. Just made sure that it is pointing to the annotation, it is referring to.

Question:

I am trying to catch an exception that is thrown within my main in my Java class.

My main's code:

public static void main(String[] args){
    new something();
    throw new RuntimeException();
}

In my aspect, I have created both after() returning: execution(* main(*)) { advice} and after() throwing(Exception e): execution(* main(*)) { advice } to find out if an exception is thrown in the main or not, in order to do something different at each advice.

Note that inside the second one, I am printing in the output the e exception using:

System.out.println("Threw an exception: " + e + "Joinpoint: " + thisJoinPoint.getSignature().toString());

The problem is that even if I throw an exception in main, and I can see from the output that the pointcut that is matched is the second one (Ouput: Threw an exception: java.lang.RuntimeExceptionJoinpoint: void main(String[]) ), I still get this error in my output:

Exception in thread "main" java.lang.RuntimeException
    at main(C.java:24)

So, as I can understand, I haven't catched the exception, I just identified that an exception happened in main.

Is there a way that I could catch this exception without having to use around() ?


Answer:

You can't suppress an exception with an after() throwing advice, you'll need to use an around() advice as you suspected.

void around(): execution(* MainClass.main(*)) {
    try {
        proceed();
    } catch (Exception e) {
        //suppress
        System.out.println("Suppressed an exception: " 
            + e + "Joinpoint: " + thisJoinPoint.getSignature().toString());
    }
}

An after() throwing advice is good to run additional code when an exception is thrown at some point of interest of yours but it won't stop the exception from propagating unless you throw another exception from your advice code (wrap the suppressed exception if you do so):

after() throwing(Exception e): execution(* MainClass.main(*)) {
    System.out.println("Threw an exception: " + e + "Joinpoint: " 
        + thisJoinPoint.getSignature().toString());
    throw new RuntimeException("Another exception", e);
}

EDIT: I'm adding an example on how to emulate before(), after() returning, after() throwing and after() advices in an around() advice following up a question in a comment on my answer.

void around(): execution(* MainClass.main(*)) {
    try {
        //before() code
        System.out.println("Before main started.");

        proceed();

        //after() returning code
        System.out.println("Main exited normally.");
    } catch (Exception e) {
        //after() throwing code suppressing exception unless you rethrow it
        System.out.println("Suppressed an exception: " + e + "Joinpoint: " 
            + thisJoinPoint.getSignature().toString());
    } finally {
        //after() code
        System.out.println("After main executed.");
    }
}

This will output the following lines when your main class is run:

Before main started.
Main started.
Suppressed an exception: java.lang.RuntimeException: errorJoinpoint: void MainClass.main(String[])
After main executed

Note that the code for the after() returning part doesn't get executed as your main class doesn't finish normally as it throws an exception instead, just as a normal after() returning advice would not run in that case.

Question:

I am trying to implement one of the suggestion given by our stackoverflow member here Logging entry, exit and exceptions for methods in java using aspects . Since this is different question in itself, posting here again.

I have tried to search but looks like different versions have different ways of doing it and unable to figure out an example online. I have tried the following simple example since I am new to aspect oriented programming and couldn't figure out how to implement. This example is throwing NPE. Please help me understand where I am doing it wrong.

==== Exception

Exception in thread "main" java.lang.NullPointerException
at aoplogging.SimpleCall.call(SimpleCall.java:13)
at aoplogging.App.main(App.java:18)

Exactly at SimpleService.simpleCall();

ApplicationContext:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">


<aop:aspectj-autoproxy />
<bean id="simpleCall" class="aoplogging.SimpleCall" />

================== App.java

package aoplogging;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {


public static void main(String[] args) {
    ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    SimpleCall call =(SimpleCall) context.getBean("simpleCall");
    call.call();
    context.close();
}

============ SimpleCall.java package aoplogging;

import org.springframework.beans.factory.annotation.Autowired;

public class SimpleCall {

@Autowired
private SimpleService SimpleService;

public void call(){


    SimpleService.simpleCall();
    try {
        SimpleService.processingOperator();
    } catch (SMSProcessingException | SMSSystemException e) {
        e.printStackTrace();
    }
}

}

=====Logging.java

package aoplogging;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Logging {
@Pointcut("execution(* aoplogging.*.*(..))")
   private void selectAll(){}

   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
   @Before("selectAll()")
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   @After("selectAll()")
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   @AfterReturning(pointcut = "selectAll()", returning="retVal")
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
    * This is the method which I would like to execute
    * if there is an exception raised by any method.
    */
   @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }

}


Answer:

I am supporting my suggestion ;).

The usage of Spring AOP/AspectJ is problematic when using beans that are not injected by using interface (using the interface ate the injection point), as the interfaces are proxied by AspectJ.

There is a way to come around this by adding proxy-target-class="true" to

<aop:aspectj-autoproxy />

but that is not a nice way.

It is much more simpler and safer to use interfaces.


EDIT: Another error is that you are missing a bean that is implementing SimpleService. It would be easier to add

<context:component-scan base-package="aoplogging" />

to your applicationContext.xml.

Then, you have to tag all beans with

@Component

in order to let Spring know that they are beans that Spring should instantiate.


EDIT: The aspect has to be annotated with both @Aspect and @Component in order to let Spring detect it.

Question:

I'm trying add some monitoring when some specific exception occurs. For example, if I have an aspect like this:

@Aspect
public class LogAspect {

  @AfterThrowing(value = "execution(* *(..))", throwing = "e")
  public void log(JoinPoint joinPoint, Throwable e){
    System.out.println("Some logging stuff");
  }
}

And test class:

 public class Example {


  public void divideByZeroWithCatch(){
    try{
      int a = 5/0;
    }
    catch (ArithmeticException e){
      System.out.println("Can not divide by zero");
    }
  }

  public void divideByZeroWithNoCatch(){
    int b = 5/0;
  }

  public static void main (String [] args){
    Example e = new Example();
    System.out.println("***** Calling method with catch block *****");
    e.divideByZeroWithCatch();
    System.out.println("***** Calling method without catch block *****");
    e.divideByZeroWithNoCatch();
  }
}

As an output i will get:

***** Calling method with catch block *****
Can not divide by zero
***** Calling method without catch block *****
Some logging stuff

I was wondering if there is way for me to intercept method execution just after throwing exception, do something in my advice and continue with executing code in corresponding catch block? So that if i call divideByZeroWithCatch()i can get:

Some logging stuff
Can not divide by zero 

Answer:

Yes, you can. You need a handler() pointcut:

package de.scrum_master.aspect;

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

@Aspect
public class LogAspect {
    @AfterThrowing(value = "execution(* *(..))", throwing = "e")
    public void log(JoinPoint thisJoinPoint, Throwable e) {
        System.out.println(thisJoinPoint + " -> " + e);
    }

    @Before("handler(*) && args(e)")
    public void logCaughtException(JoinPoint thisJoinPoint, Exception e) {
        System.out.println(thisJoinPoint + " -> " + e);
    }
}

Log output, assuming class Example is in package de.scrum_master.app:

***** Calling method with catch block *****
handler(catch(ArithmeticException)) -> java.lang.ArithmeticException: / by zero
Can not divide by zero
***** Calling method without catch block *****
execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zero
execution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:13)
    at de.scrum_master.app.Example.main(Example.java:21)

Update: If you want to know where the exception handler is located, there is a simple way: use the enclosing joinpoint's static part. You can also get information about parameter names and types etc. Just use code completion in order to see which methods are available.

@Before("handler(*) && args(e)")
public void logCaughtException(
    JoinPoint thisJoinPoint,
    JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart,
    Exception e
) {
    // Exception handler
    System.out.println(thisJoinPoint.getSignature() + " -> " + e);

    // Method signature + parameter types/names
    MethodSignature methodSignature = (MethodSignature) thisEnclosingJoinPointStaticPart.getSignature();
    System.out.println("    " + methodSignature);
    Class<?>[] paramTypes = methodSignature.getParameterTypes();
    String[] paramNames = methodSignature.getParameterNames();
    for (int i = 0; i < paramNames.length; i++)
        System.out.println("      " + paramTypes[i].getName() + " " + paramNames[i]);

    // Method annotations - attention, reflection!
    Method method = methodSignature.getMethod();
    for (Annotation annotation: method.getAnnotations())
        System.out.println("    " + annotation);
}

Now update your code like this:

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int id();
    String name();
    String remark();
}
package de.scrum_master.app;

public class Example {
    @MyAnnotation(id = 11, name = "John", remark = "my best friend")
    public void divideByZeroWithCatch(int dividend, String someText) {
        try {
            int a = 5 / 0;
        } catch (ArithmeticException e) {
            System.out.println("Can not divide by zero");
        }
    }

    public void divideByZeroWithNoCatch() {
        int b = 5 / 0;
    }

    public static void main(String[] args) {
        Example e = new Example();
        System.out.println("***** Calling method with catch block *****");
        e.divideByZeroWithCatch(123, "Hello world!");
        System.out.println("***** Calling method without catch block *****");
        e.divideByZeroWithNoCatch();
    }
}

Then the console log says:

***** Calling method with catch block *****
catch(ArithmeticException) -> java.lang.ArithmeticException: / by zero
    void de.scrum_master.app.Example.divideByZeroWithCatch(int, String)
      int dividend
      java.lang.String someText
    @de.scrum_master.app.MyAnnotation(id=11, name=John, remark=my best friend)
Can not divide by zero
***** Calling method without catch block *****
execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zero
execution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:14)
    at de.scrum_master.app.Example.main(Example.java:22)

If that is good enough for you, then you are fine. But beware, the static part is not the full joinpoint, so you cannot access parameter values from there. In order to do that you have to do manual bookkeeping. And this is possibly expensive and can slow down your application. But for what it is worth, I show you how to do it:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class LogAspect {
    private ThreadLocal<JoinPoint> enclosingJoinPoint;

    @AfterThrowing(value = "execution(* *(..))", throwing = "e")
    public void log(JoinPoint thisJoinPoint, Throwable e) {
        System.out.println(thisJoinPoint + " -> " + e);
    }

    @Before("execution(* *(..)) && within(de.scrum_master.app..*)")
    public void recordJoinPoint(JoinPoint thisJoinPoint) {
        if (enclosingJoinPoint == null)
            enclosingJoinPoint = ThreadLocal.withInitial(() -> thisJoinPoint);
        else
            enclosingJoinPoint.set(thisJoinPoint);
    }

    @Before("handler(*) && args(e)")
    public void logCaughtException(JoinPoint thisJoinPoint, Exception e) {
        // Exception handler
        System.out.println(thisJoinPoint + " -> " + e);

        // Method signature + parameter types/names
        JoinPoint enclosingJP = enclosingJoinPoint.get();
        MethodSignature methodSignature = (MethodSignature) enclosingJP.getSignature();
        System.out.println("    " + methodSignature);
        Class<?>[] paramTypes = methodSignature.getParameterTypes();
        String[] paramNames = methodSignature.getParameterNames();
        Object[] paramValues = enclosingJP.getArgs();
        for (int i = 0; i < paramNames.length; i++)
            System.out.println("      " + paramTypes[i].getName() + " " + paramNames[i] + " = " + paramValues[i]);

        // Target object upon which method is executed
        System.out.println("    " + enclosingJP.getTarget());

        // Method annotations - attention, reflection!
        Method method = methodSignature.getMethod();
        for (Annotation annotation: method.getAnnotations())
            System.out.println("    " + annotation);
    }
}

Why do we need a ThreadLocal member for the joinpoint bookkeeping? Well, because obviously we would get into problems in multi-threaded applications otherwise.

Now the console log says:

***** Calling method with catch block *****
handler(catch(ArithmeticException)) -> java.lang.ArithmeticException: / by zero
    void de.scrum_master.app.Example.divideByZeroWithCatch(int, String)
      int dividend = 123
      java.lang.String someText = Hello world!
    de.scrum_master.app.Example@4783da3f
    @de.scrum_master.app.MyAnnotation(id=11, name=John, remark=my best friend)
Can not divide by zero
***** Calling method without catch block *****
execution(void de.scrum_master.app.Example.divideByZeroWithNoCatch()) -> java.lang.ArithmeticException: / by zero
execution(void de.scrum_master.app.Example.main(String[])) -> java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at de.scrum_master.app.Example.divideByZeroWithNoCatch(Example.java:14)
    at de.scrum_master.app.Example.main(Example.java:22)

Question:

I've encountered the following exception in an application that is being built with Gradle and uses AspectJ. The app works fine when started from within Eclipse but fails to start once built with Gradle:

Caused by: java.lang.AssertionError: java.lang.ClassNotFoundException: net.openhft.chronicle.hash.VanillaGlobalMutableState$$Native
at net.openhft.chronicle.values.ValueModel.createClass(ValueModel.java:313) ~[chronicle-values-1.0.3-alpha.jar!/:na]
at net.openhft.chronicle.values.ValueModel.createNativeClass(ValueModel.java:286) ~[chronicle-values-1.0.3-alpha.jar!/:na]
at net.openhft.chronicle.values.ValueModel.nativeClass(ValueModel.java:268) ~[chronicle-values-1.0.3-alpha.jar!/:na]
at net.openhft.chronicle.values.Values.nativeClassFor(Values.java:51) ~[chronicle-values-1.0.3-alpha.jar!/:na]
at net.openhft.chronicle.values.Values.newNativeReference(Values.java:38) ~[chronicle-values-1.0.3-alpha.jar!/:na]
at net.openhft.chronicle.hash.impl.VanillaChronicleHash.createGlobalMutableState(VanillaChronicleHash.java:324) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.hash.impl.VanillaChronicleHash.initOwnTransients(VanillaChronicleHash.java:373) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.hash.impl.VanillaChronicleHash.initTransients(VanillaChronicleHash.java:369) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.VanillaChronicleMap.initTransients(VanillaChronicleMap.java:146) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.VanillaChronicleMap.<init>(VanillaChronicleMap.java:102) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder.newMap(ChronicleMapBuilder.java:1703) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder.lambda$createWithFile$93(ChronicleMapBuilder.java:1449) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder$$Lambda$7/78866071.fileIOAction(Unknown Source) ~[na:na]
at net.openhft.chronicle.map.ChronicleMapBuilder.lambda$fileLockedIO$92(ChronicleMapBuilder.java:182) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder$$Lambda$8/862681096.apply(Unknown Source) ~[na:na]
at java.util.concurrent.ConcurrentHashMap.compute(Unknown Source) ~[na:1.8.0_45]
at net.openhft.chronicle.map.ChronicleMapBuilder.fileLockedIO(ChronicleMapBuilder.java:179) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder.createWithFile(ChronicleMapBuilder.java:1447) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]
at net.openhft.chronicle.map.ChronicleMapBuilder.createPersistedTo(ChronicleMapBuilder.java:1400) ~[chronicle-map-3.5.0-rc.jar!/:3.5.0-rc]

In my build.gradle I have:

    compile "net.openhft:chronicle-map:3.5.0-rc"

I've also tried this with earlier versions, without success.

One thing I have noticed when starting from Eclipse is that this new warning shows up when Chronicle is fist accessed:

warning: Supported source version 'RELEASE_7' from annotation processor  'org.neo4j.kernel.impl.annotations.ServiceProcessor' less than -source '1.8'
warning: Supported source version 'RELEASE_7' from annotation processor 'org.neo4j.kernel.impl.annotations.DocumentationProcessor' less than -source '1.8'

but I am not sure if that is related. Am I missing some other dependency?

Edit: I should also mentioned that I use Spring and that my Chronicle map is instantiated as part of a Spring bean.

Edit 2: Debug logging didn't yield anything useful. I'll try to downgrade to an older version of chronicle map next.

Edit 3: It works when building with

compile "net.openhft:chronicle-map:2.4.12"

Edit 4: Same error with new 3.6.0-rc

Edit 5: I have

compile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())

in my build.gradle in order to add the tools.jar (Gradle doesn't have provide afaik). It is also part of the resulting (fat) jar file that I start.


Answer:

Chronicle Map version 3.7.0-rc doesn't have this issue. It emits some no-harm warnings, which will go away with the next released version.

Question:

We're trying to implement AspectJ @Aspect into our existing software for executing some code after a service call is made.

Note:

  • We have service interfaces and implementations being @Autowired throughout the project via rest controllers as well as other service implementations.
  • This project is entirely a Java Configuration with no XML whatsoever.
  • We're using Spring 4.1.2 RELEASE deployed on Tomcat 7.0.54.

Issue:

When we added @EnableAspectJAutoProxy into our main @JavaConfig, we experience the following exception:

Unresolvable circular reference.

Which fails every @Autowired attempt on a long list of beans.

Tried:

  • Removed the @EnableAspectJAutoProxy annotation which autowires everything correctly but our @Aspect never gets invoked.
  • Added the CGLIB support in the annotation by declaring proxytargetclass=true to no avail.
  • We've tried following this documentation directly from Spring: @EnableAspectJAutoProxy Javadoc

This seems to be an issue with AspectJ's proxy mechanism dealing with autowired dependencies.

Why does this occur when we add the @EnableAspectJAutoProxy?

Our Java Config:

@Configuration
@EnableWebMvc
@EnableJpaRepositories(basePackages ={"com.company.product.persistence.repository"})
@EnableTransactionManagement
@EnableSwagger
@EnableAspectJAutoProxy
@PropertySource({"classpath:hibernate.properties",
                 "classpath:auth.properties",
                 "classpath:mail.properties",
                 "classpath:locations.properties"
                })
@ComponentScan(basePackages = {"com.company.product"})
public class WebConfig extends WebMvcConfigurerAdapter {
    //Bean declarations here.
    //Note: All services/repos/controllers are annotation based.
}

Aspect implementation:

@Aspect
@Component
public class PostMessageAspect {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @After("execution(*com.company.product.persistence.serviceImpl.event.eventServiceImpl.methodCall(..))")
    public void postMessageRun(final JoinPoint joinPoint) {
        logger.info("CALLED AFTER METHOD");
    }
}

Update:

Managed to get AOP/AspectJ working perfectly fine on one dev machine only requiring a minor change to our Spring Security config. We are both using Intellij, openJDK 1.7.0_65 on Ubuntu 14.0.4 running on default instances of Tomcat 7.0.56. On the other machine running the same software stack, gets the following.

Stack Trace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dispatchingMessageController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.event.DispatchingEventService com.apx.efm.controllers.message.DispatchingMessageController.dispatchingEventService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dispatchingEventServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingAd dressesService com.apx.efm.persistence.serviceImpl.event.DispatchingEventServiceImpl.buildingAddressesService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'buildingAddressServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingService com.apx.efm.persistence.serviceImpl.building.BuildingAddressServiceImpl.buildingService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'buildingServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingAddressesService com.apx.efm.persistence.serviceImpl.building.BuildingServiceImpl.buildingAddressesService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.apx.efm.persistence.service.user.EfmUserService com.apx.efm.application.config.SecurityConfig.efmUserService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'efmUserServiceImpl' defined in file [/home/apxdev4/Development/GitRepositories/efim-restful-web-service/target/EFIM/WEB-INF/classes/com/apx/efm/persistence/serviceImpl/user/EfmUserServiceImpl.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'methodSecurityInterceptor': Requested bean is currently in creation: Is there an unresolvable circular reference?


Answer:

This was entirely an issue with our Spring configuration. Our Spring Security configuration was trying to @Autowired beans while they were still in the middle of being processed by our main application configuration. We solved this by ensuring that Spring Security gets configured after the main @Configuration.

@Override
public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
    // Initialize web mvc
    appContext.setDisplayName("APP");
    appContext.register(WebConfig.class);
    appContext.register(SecurityConfig.class);

    // Rest omitted (listeners, dispatcher servlet, etc.)
}

Question:

I have a Spring MVC application made with MyEclipse, which contains generated sources as well as my own sources, plus aspects that I defined on the generated classes. Everything compiled fine in MyEclipse, but I want now to switch to Maven in order to use a continuous integration server.

I have been fiddling with the pom.xml for a long while now, and I hit a wall I can't seem to get around. When maven gets to the moment of weaving aspects, I get the following exception (just the first few lines for brevity):

[INFO] [aspectj:compile {execution: default}]
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[ERROR] ABORT
May 30, 2016 11:48:05 AM org.aspectj.weaver.tools.Jdk14Trace info
INFO: Dumping to /var/atlassian/application-data/bamboo/xml-data/build-dir/OW-BUIL-JOB1/./ajcore.20160530.114805.876.txt
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] AJC compiler errors:
abort ABORT -- (NullPointerException) null
null
java.lang.NullPointerException
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.AnnotationDiscoveryVisitor.resolveAnnotations(AnnotationDiscoveryVisitor.java:238)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.AnnotationDiscoveryVisitor.visit(AnnotationDiscoveryVisitor.java:217)
    at org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.traverse(TypeDeclaration.java:1348)
    at org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.traverse(CompilationUnitDeclaration.java:748)
    ...

My pom.xml is too long to paste it here, but the build part is as follows (let me know if you want to see some of the dependencies):

<build>
    <directory>bin</directory>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <id>add-source</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>src</source>
                            <source>generated</source>
                            <source>resources</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
                <excludes>
                    <exclude>main/</exclude>
                    <exclude>test/</exclude>
                </excludes>
                <useIncrementalCompilation>true</useIncrementalCompilation>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.8</version>
            <configuration>
                <showWeaveInfo>true</showWeaveInfo>
                <source>1.6</source>
                <target>1.6</target>
                <Xlint>ignore</Xlint>
                <complianceLevel>1.6</complianceLevel>
                <encoding>UTF-8</encoding>
                <verbose>true</verbose>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <webXml>${project.basedir}/WebRoot/WEB-INF/web.xml</webXml>
                <warName>oligoWorld</warName>
                <outputDirectory>${project.basedir}</outputDirectory>
            </configuration>
        </plugin>
    </plugins>
    <pluginManagement>
        <plugins>
            <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
            <plugin>
                <groupId>org.eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                            <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>aspectj-maven-plugin</artifactId>
                                    <versionRange>[1.8,)</versionRange>
                                    <goals>
                                        <goal>compile</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <execute />
                                </action>
                            </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

Anybody seeing anything wrong or missing that might cause that exception? FYI, the version of my aspectj dependencies (aspectjrt, aspectjtools and aspectjweaver) is 1.8.7.


Answer:

I seem to have found the problem. In the pom.xml I had the dependency for aspectjtools listed with all the other dependencies in the dependencies section of the pom file, outside the aspectj-maven-plugin definition. Instead, I moved it inside the plugin; also, I changed the aspectj libraries' version to 1.8.9, as it seems 1.8.7 exhibits a bug similar to what I have found. After this, everything worked. So here's my modified definition for the aspectj-maven-plugin for reference:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.8</version>
            <dependencies> <!-- The change that fixed it starts here... -->
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>1.8.9</version>
                </dependency>
            </dependencies> <!-- ...and ends here. -->
            <configuration>
                <showWeaveInfo>true</showWeaveInfo>
                <source>1.6</source>
                <target>1.6</target>
                <Xlint>ignore</Xlint>
                <complianceLevel>1.6</complianceLevel>
                <encoding>UTF-8</encoding>
                <verbose>true</verbose>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
        </plugin>

Question:

I'm debugging a strange connection refused error thrown from my Java application (JDK 1.8.0_65).

I have got Wireshark capture, but it includes both normal and error TCP segments and I have no way to distinguish which is which.

I want to know if I can make Java log out source port number when it throws ConnectException, so I can search using it. Can I use tools like AspectJ to do this?

FYI, here's the stack trace:

Caused by: java.net.ConnectException: Connection refused: connect
                at java.net.DualStackPlainSocketImpl.connect0(Native Method) ~[na:1.8.0_65]
                at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) ~[na:1.8.0_65]
                at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_65]
                at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_65]
                at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_65]
                at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_65]
                at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_65]
                at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_65]
...

Answer:

If the client socket was created without an explicit bind(), there's no way to find out which source port was used to try and establish the connection. So in order to be able to report on the source port for debugging purposes, you need to do an explicit bind before the connect call. If you have access to the source of the client code, you could update it in a similar way:

SocketAddress target = new InetSocketAddress(host, port);
int localPort = -1;
try (Socket socket = new Socket()) {
    socket.bind(null);
    localPort = socket.getLocalPort();
    socket.connect(target, timeout);
} catch (IOException e) {
    throw new IOException(
            String.format("couldn't connect to %s from port %d", target, localPort), e);
}

If you can't change the client source code, you could use the following aspect to weave the client code. It works by intercepting method calls to Socket.connect(...), determines whether the socket was already bound to a port and if not, will do a bind(null), which should find an available port to bind to.

import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public aspect SocketExceptionLoggerAspect {

    private static final Logger logger = LoggerFactory
            .getLogger(SocketExceptionLoggerAspect.class);

    pointcut callToSocketConnect(SocketAddress target): 
        call(void Socket+.connect(..)) && args(target, ..);

    void around(SocketAddress target, Socket socket) : 
        callToSocketConnect(target) && target(socket) {

        int localPort = socket.getLocalPort();
        if (localPort == -1) {
            try {
                socket.bind(null);
                localPort = socket.getLocalPort();
            } catch (IOException e) {
            }
        }
        try {
            proceed(target, socket);
        } catch (IOException e) {
            logger.error(String.format("couldn't connect to %s from port %d", target,
                    localPort), e);
        }
    }
}

Example output: SocketExceptionLoggerAspect - couldn't connect to stackoverflow.com/104.16.33.249:123 from port 49840 <stack trace...>

Question:

We are using AOP and everything works fine, I have added @Transactional.

This is happening when i move from one method to another and i can't find any connection!! !!!! annotation and the application is not starting and throwing exception:

 Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0000000: 014e b800 2699 0032 2ab4 0053 c700 202a
    0000010: bb00 2e59 b200 1412 55b7 0031 b500 53b8


    0000020: 0034 2ab4 0053 b900 3a02 0057 2ab4 0053
    0000030: 2bb6 0040 a700 0a2b b900 4401 004e 2db0
    0000040:          



at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2570)
at java.lang.Class.getDeclaredFields(Class.java:1903)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.compiledByAjc(AbstractAspectJAdvisorFactory.java:120)
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.isAspect(AbstractAspectJAdvisorFactory.java:105)
at org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(BeanFactoryAspectJAdvisorsBuilder.java:103)
at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:87)
at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:103)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:289)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:958)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:930)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:465)

The only thing that cause this is when i add @Transactional on top of the Class of on top of one of the methods.. I don't have a clue. Please update me if you need more details in order to solve this.

EDIT:

I am using JDK 1.8_05, Spring version is 4.0.3 with Instrumentation agent. I am working with Eclipse Luna Release (4.4.0) and OS is windows 8.

The weird thing is that if i move the @Transactional annotation between 2 methods.. One of them works and the other one just make the app crash on startup..

Thanks


Answer:

After long search... I found the solution for this.. Although it seems weird, I tried to update spring version and it solve the issue.. Spring version was updated from 4.0.3 to 4.1.4

Thanks for those who tried to help me :)

Question:

Is there any way to intercept exception and show meaningful message to end customer? I am trying to authorise my api using spring AOP and if end user is not authorised to access the API, I am throwing exception.

@Aspect
public class AuthorizationAspect {
  @Pointcut("@annotation(AuthenticateAccount)")
    public void authorized() {}

   private boolean isAuthorized() {
   // logic to check is user is authorised to call the api
   }

    @Before("authorized()")
    public void beforeControllerCall(JoinPoint joinPoint) throws UnauthorizedException {

        if(!isAuthorized)) {
            throw new UnauthorizedException("You don't have rights over this API");
        }

    }
}

By throwing the exception, I am able to prevent the acess to API, but it does not return me meaningful message which I am trying to throw in exception.

Has anyone worked with such use case and can help me with this?


Answer:

You can use global exception handling using @ControllerAdvice. Create your custom exception and throw that exception from Aspect class. You can create @ControllerAdvice annotated class like this:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {UnauthorizedException.class})
    public ResponseEntity<Object> handleException(UnauthorizedException ex){
        return new ResponseEntity<Object>(
      ex.getMessage(), new HttpHeaders(), HttpStatus.FORBIDDEN);
    }

}

EDIT:

Please find spring boot global exception handling code below:

DemoController.java

@RestController
public class DemoController {

    @GetMapping("/hello")
    String hello(){
        return "Message from controller if there is no exception";
    }
}

AuthException .java

public class AuthException extends Exception{
    AuthException(String msg){
        super(msg);
    }
}

AopValidator .java

@Aspect
@Component
public class AopValidator {

    @Before("execution(String hello())")
     public void test() throws AuthException{
         throw new AuthException("Exception message from AOP on unauthorized access");
     }
}

GlobalExceptionHandler.java

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(AuthException.class)
    ResponseEntity<Object> handleException(AuthException ex){
        return new ResponseEntity<>(ex.getMessage(), new HttpHeaders(), HttpStatus.FORBIDDEN);
    }
}

Question:

I have and Aspect in spring based on aspectJ:

@After("execution(* ...)
public void stopTotalTimerAndMarkSucess(JoinPoint joinPoint) {...}

@AfterThrowing("execution(* c ..)
public void markError(JoinPoint joinPoint) {...}

I need to exclude @After execution when my under method throws and exception. Now when a method throws an exception are executed both (@After and @AfterThrowing).


Answer:

You need @AfterReturning annotation rather than @After.

@AfterReturning:

After returning advice runs when a matched method execution returns normally. It is declared using the @AfterReturning annotation (...)

@After:

After (finally) advice runs however a matched method execution exits. It is declared using the @After annotation. After advice must be prepared to handle both normal and exception return conditions. It is typically used for releasing resources, etc.

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

Question:

I am trying to perform null checks on my methods using simple custom @NotNull annotation i.e. I declare method as myMethod(@NotNull String name, String description) and when someone calls this method with null value passed as the 'name' argument an exception is thrown.

I already have an implementation of a simple aspect using aspectj. This solution works quite well for me. The one exception is constructors of inner classes. In such case the aspect crashes because of an exception inside java.lang.reflect.Parameter:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at java.lang.reflect.Parameter.getDeclaredAnnotations(Parameter.java:305)
    at java.lang.reflect.Parameter.declaredAnnotations(Parameter.java:342)
    at java.lang.reflect.Parameter.getAnnotation(Parameter.java:287)
    at java.lang.reflect.Parameter.getDeclaredAnnotation(Parameter.java:315)
    at ValidationAspect.checkNotNullArguments(ValidationAspect.java:22)
    at OuterClass$InnerClass.<init>(OuterClass.java:4)
    at OuterClass.constructInnerClass(OuterClass.java:14)
    at Main.main(Main.java:5)

Simplified implementation:

Aspect:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.ConstructorSignature;

import java.lang.reflect.Parameter;

@Aspect
public class ValidationAspect {

  @Pointcut("execution(*.new(.., @NotNull (*), ..))")
  private void anyConstructorWithNotNullParam() {}

  @Before("anyConstructorWithNotNullParam()")
  public void checkNotNullArguments(JoinPoint joinPoint) {
    ConstructorSignature signature = (ConstructorSignature) joinPoint.getSignature();
    Object[] args = joinPoint.getArgs();
    Parameter[] params = signature.getConstructor().getParameters();

    for(int i = 0; i < args.length; i++) {
      if(params[i].getDeclaredAnnotation(NotNull.class) != null) {
        if (args[i] == null) {
          throw new IllegalArgumentException("Illegal null argument");
        }
      }
    }
  }
}

Annotation:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER})
public @interface NotNull { }

Test class:

public class OuterClass {

  public class InnerClass {
    public InnerClass(
        @NotNull String name
    ) {
      System.out.println(String.format("Construct inner class with name: %s", name));
    }
  }

  public InnerClass constructInnerClass(
      String name
  ) {
    return new InnerClass(name);
  }
}

Usage:

public class Main {

  public static void main(String[] args) {
    OuterClass outObj = new OuterClass();
    outObj.constructInnerClass("myName");
  }
}

As far as I can tell, this is caused by java passing the enclosing class object as the first argument to the constructor of the inner class (which I was told is standard behavior). The problem is, that params[i].executable.getParameterAnnotations() does not seem to know about the additional argument and returns annotations only for the "normal" parameters

I feel like this is a bug in either aspectj or java.lang.reflection. But as I cannot find any bug report for this, it seems more likely to me that I am doing something wrong. The app runs on java 8 (tried multiple different builds of the oracle jdk and the last openjkd build) and aspectj 1.8.13 (but tried also 1.9.4).

So my question(s): Is this a known bug? Is there some flaw in my implementation? Is there some workaround? (I guess it would not be that hard to match the annotations to the parameters manually. But as I have very limited knowledge about java reflection, I am not really able to foresee the consequences).

Edited: provided working example


Answer:

Okay, I was too curious and played around with my own MCVE. I could rule out AspectJ as the culprit and pinned the problem down to a JDK/JRE problem:

The thing with inner (non-static) class constructors is that their first parameter is always an instance of the outer object. Java 8 - I tried with both 1.8.0_152 and 1.8.0_211 - contains a reflection off-by-one bug. Basically it moves the annotations of real inner constructor parameters one index up, e.g. the annotation parameters for the first constructor argument are stored in index 0 which actually should contain the annotations for the outer object instance. My sample code explains it better, I guess:

package de.scrum_master.app;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(PARAMETER)
public @interface NotNull {}
package de.scrum_master.app;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class Application {
  class Inner {
    public Inner(@NotNull String text) {
      System.out.println("Constructing inner with " + text);
    }
  }

  public static void main(String[] args) throws NoSuchMethodException, SecurityException {
      Constructor<Inner> constructor = Inner.class.getConstructor(Application.class, String.class);
      System.out.println(constructor);
      for (Parameter parameter : constructor.getParameters()) {
        System.out.println("  " + parameter);
        for (Annotation annotation : parameter.getAnnotations())
          System.out.println("    " + annotation);
      }
  }
}

This reproduces your problem for JDK 8:

public de.scrum_master.app.Application$Inner(de.scrum_master.app.Application,java.lang.String)
  de.scrum_master.app.Application arg0
    @de.scrum_master.app.NotNull()
  java.lang.String arg1
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at java.lang.reflect.Parameter.getDeclaredAnnotations(Parameter.java:305)
    at java.lang.reflect.Parameter.getAnnotations(Parameter.java:333)
    at de.scrum_master.app.Application.main(Application.java:19)

But if you run with JDK 11 (I used 11.0.2) everything works as expected, also if I use an aspect with an advice like yours:

public de.scrum_master.app.Application$Inner(de.scrum_master.app.Application,java.lang.String)
  de.scrum_master.app.Application arg0
  java.lang.String arg1
    @de.scrum_master.app.NotNull()

I haven't bothered to look through all JDK release notes in order to find out whether this was fixed on purpose or by chance and in which JDK version (9, 10, 11), but at least I can tell you that after an update to JDK 11 you should be fine.

Question:

I try to complete LTW example from AspectJ Cookbook, but it doesn't work. I created and compiled Java class:

public class MyClass{
public void foo(int number, String name){
    System.out.println("Inside of foo");
}

public static void main(String[] args) {
    MyClass myObject = new MyClass();
    myObject.foo(1, "Str");
}
}

it works just fine:

c:\TEMP\examples>java MyClass
Inside of foo

Then I created aspect:

public aspect HelloWorld{
pointcut callPointcut(): call(void MyClass.foo(int, String));

before() : callPointcut(){
    System.out.println("Hello World from advice");
}
}

compiled it:

c:\TEMP\examples>c:\tools\aspectj1.8\bin\ajc -outjar my.jar HelloWorld.aj
C:\TEMP\examples\HelloWorld.aj:4 [warning] no match for this type name:       MyClass [Xlint:invalidAbsoluteTypeName]
pointcut callPointcut(): call(void MyClass.foo(int, String));
                                   ^^^^^^^^^
    [Xlint:invalidAbsoluteTypeName]

1 warning

And then try to run:

c:\TEMP\examples>java -classpath "C:\tools\aspectj1.8\lib\aspectjweaver.jar" "-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader" -Daj.class.path=. "-Daj.aspect.path=c:\TEMP\examples" MyClass
java.lang.ExceptionInInitializerError
        at org.aspectj.weaver.WeaverMessages.<clinit>(WeaverMessages.java:18)
        at org.aspectj.weaver.bcel.ClassPathManager.addPath(ClassPathManager.java:81)
        at org.aspectj.weaver.bcel.ClassPathManager.<init>(ClassPathManager.java:63)
        at org.aspectj.weaver.bcel.BcelWorld.<init>(BcelWorld.java:285)
        at org.aspectj.weaver.tools.WeavingAdaptor.init(WeavingAdaptor.java:176)
        at org.aspectj.weaver.tools.WeavingAdaptor.<init>(WeavingAdaptor.java:109)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:75)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:52)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
        at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
Caused by: java.lang.IllegalStateException: recursive invocation
        at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
        at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
        at java.util.ServiceLoader.loadInstalled(Unknown Source)
        at java.util.ResourceBundle.<clinit>(Unknown Source)
        ... 17 more
Error occurred during initialization of VM
java.lang.ExceptionInInitializerError
        at org.aspectj.weaver.WeaverMessages.<clinit>(WeaverMessages.java:18)
        at org.aspectj.weaver.bcel.ClassPathManager.addPath(ClassPathManager.java:81)
        at org.aspectj.weaver.bcel.ClassPathManager.<init>(ClassPathManager.java:63)
        at org.aspectj.weaver.bcel.BcelWorld.<init>(BcelWorld.java:285)
        at org.aspectj.weaver.tools.WeavingAdaptor.init(WeavingAdaptor.java:176)
        at org.aspectj.weaver.tools.WeavingAdaptor.<init>(WeavingAdaptor.java:109)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:75)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:52)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
        at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
Caused by: java.lang.IllegalStateException: recursive invocation
        at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
        at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
        at java.util.ServiceLoader.loadInstalled(Unknown Source)
        at java.util.ResourceBundle.<clinit>(Unknown Source)
        at org.aspectj.weaver.WeaverMessages.<clinit>(WeaverMessages.java:18)
        at org.aspectj.weaver.bcel.ClassPathManager.addPath(ClassPathManager.java:81)
        at org.aspectj.weaver.bcel.ClassPathManager.<init>(ClassPathManager.java:63)
        at org.aspectj.weaver.bcel.BcelWorld.<init>(BcelWorld.java:285)
        at org.aspectj.weaver.tools.WeavingAdaptor.init(WeavingAdaptor.java:176)
        at org.aspectj.weaver.tools.WeavingAdaptor.<init>(WeavingAdaptor.java:109)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:75)
        at org.aspectj.weaver.loadtime.WeavingURLClassLoader.<init>(WeavingURLClassLoader.java:52)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.lang.SystemClassLoaderAction.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
        at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)

I try different solutions and exception occurs only if I provide -Daj.aspect.path=c:\TEMP\examples, but as far as I understand it is because weaver will load aspect only of this option is provided. Without this option Java program works without any aspects weaved at load time.


Answer:

Can you use the javaagent? I feel it is simpler than modifying the class loader:

javac MyClass.java

ajc HelloWorld.java -1.8 -outxml -d out

export CLASSPATH=.:out:$CLASSPATH

java -javaagent:$AJHOME/lib/aspectjweaver.jar MyClass
Hello World from advice
Inside of foo

The -outxml option on the ajc call is what produces the META-INF/aop-ajc.xml file in the out folder, and that is what the agent will look for to turn on weaving. (That xml file will simply list the aspects to 'turn on' and optionally some extra weaver configuration)

Question:

I have a requirement to intercept every thrown exception and do something with it. I am using this part of code:

@Aspect
@Component
class Advice
{
    @AfterThrowing(pointcut = "execution(* mail.service..*.*(..))", throwing = "throwable")
    public void sendError(Throwable throwable)
    {
    System.out.println("exception thrown");
    }
}

This somehow does not work as I expected. This pointcut seems to 'affect' only the public methods(which is expected from Spring AOP, I suppose?) but it prints the String only in certain methods, for example, methods that are declared in my Spring configuration class(i guess its because they are initialized before the app starts) and not in the other ones.

I tried to get this aspect working for any exception thrown, but I had no success. Is this somehow connected with the fact that I am using Spring AOP and not full AspectJ?

Also, my project is written in Kotlin(I wrote the aspect in Java so IJ can support it), will this have an impact on using AspectJ? I had a lot of troubles to get it working (because of final classes) and I am wondering if it's going to be a lot harder when I start writing more advanced AspectJ code.

Thanks!


Answer:

Yes, Spring AOP only works for Spring components and only for public methods (plus protected and package-protected ones for CGLIB proxies). It also does not work for self-invoked methods like this.doSomething() because those do not go through the proxy. Only if your exceptions escalate outside a method called via proxy, Spring AOP will be able to intercept it.

AspectJ with LTW (load-time weaving) or CTW (compile-time weaving) does not have any of those limitations, plus you can also handle exceptions in constructors, not just in methods.

Never having used Kotlin before, I cannot tell you what possible problems might be there, but final classes should not be a problem as such because AspectJ instruments the classes' bytecode directly, not via proxies. Just give it a try.

BTW, just in case you only use Spring because of AOP: You do not need to use Spring at all in order to apply AOP to your classes because AspectJ is 100% independent of Spring. You can use them together or not, your choice. I for example never use Spring, but just Java SE + AspectJ.

Question:

I'm trying to catch all MySpecificException exceptions thrown from an application code via aspectj.

There are lots of places where this exception can be thrown. Once the exception is thrown I want to log it or do some operation (regardless if it was caught later or not).

I've tried using:

@AfterThrowing(value = "(execution(* *.*(..))), throwing = "throwable")

but this is an overkill since it catches all the exceptions. I can filter manually later, but I'm trying to avoid this (due to my apps nature, it causes load time problems in some cases due to class loader issues)

I've also tried:

@AfterThrowing(value = "(execution(* *.*(..))) throws MySpecificException, throwing = "throwable")

but it's not enough since what if the method declares that it throws lots of exceptions?

Any suggestions on how to catch only my relevant exceptions without filtering them inside the pointcut implementation?

Thanks


Answer:

Your code is not executable, please provide an MCVE or at least a full aspect next time. You do not even provide the advice's signature. This is not a good way to ask questions on SO. As a user with 1,000+ reputation points you should know that.

Anyway, the answer to your question is actually very simple. Assuming you have this sample code:

Exception class + driver application:

package de.scrum_master.app;

public class MySpecificException extends Exception {
  private static final long serialVersionUID = 1L;
}
package de.scrum_master.app;

import java.io.IOException;

public class Application {
  public String doSomething(Integer number) {
    return number.toString();
  }

  public void doSomethingElse(boolean doThrow) throws MySpecificException {
    if (doThrow)
      throw new MySpecificException();
  }

  public void doWhatever(boolean doThrow) throws MySpecificException, IOException {
    if (doThrow)
      throw new MySpecificException();
    else
      throw new IOException();
  }

  public static void main(String[] args) throws MySpecificException, IOException {
    Application application = new Application();

    // Just so as not to mess up the console output in the IDE for this demo
    System.setErr(System.out);

    // No exceptions here
    application.doSomething(11);
    application.doSomethingElse(false);

    // Let's catch some exceptions
    try {
      application.doSomethingElse(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(true);
    } catch (MySpecificException e) {
      System.out.println("Caught " + e);
    }
    try {
      application.doWhatever(false);
    } catch (IOException e) {
      System.out.println("Caught " + e);
    }

    // Do not catch this one
    application.doSomethingElse(true);
  }
}

Console log without aspect:

Caught de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)

No surprises here. We have caught and uncaught exceptions of different types. Now we want to have an aspect logging specifically all occurrences of MySpecificException, no matter if they get caught or not.

Aspect:

package de.scrum_master.aspect;

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

import de.scrum_master.app.MySpecificException;

@Aspect
public class ExceptionLogger {
  @AfterThrowing(value = "(execution(* *.*(..)))", throwing = "mySpecificException")
  public void logException(JoinPoint thisJoinPoint, MySpecificException mySpecificException) {
    System.out.println(thisJoinPoint + " -> " + mySpecificException);
  }
}

See the advice method's signature? Just limit the exception parameter to the desired type.

Console log with aspect:

execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.doWhatever(boolean)) -> de.scrum_master.app.MySpecificException
Caught de.scrum_master.app.MySpecificException
Caught java.io.IOException
execution(void de.scrum_master.app.Application.doSomethingElse(boolean)) -> de.scrum_master.app.MySpecificException
execution(void de.scrum_master.app.Application.main(String[])) -> de.scrum_master.app.MySpecificException
Exception in thread "main" de.scrum_master.app.MySpecificException
    at de.scrum_master.app.Application.doSomethingElse(Application.java:12)
    at de.scrum_master.app.Application.main(Application.java:50)

Question:

Here's MVCE https://github.com/yami12376/AspectJ

  1. Add VM arguments to Run/Debug configuration of Junit test, in my case:

    -javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar

    -javaagent:C:\aspectjWeaver\aspectjweaver-1.6.11.jar

  2. In my case i added this in JAVA build path: \target\classes\META-INF from src/main/resources

  3. Run Junit test

If you delete aop.xml it's still weaving type org.*

but on the other hand aop.xml should not weave it beacuse it has: <include within="com.*"/> Why does it weave something other than com.* ?

Finally i want that MyAspect will be called when running Junit test based on @Around("execution(* *(..))")

As you can see now it is not getting called.

I've made my example based on https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-first-example

When running JUnit test i see this error:

http://wklej.org/id/3066582/

 [AppClassLoader@18b4aac2] warning parse definitions failed -- (NullPointerException) null
null
java.lang.NullPointerException
    at org.aspectj.weaver.loadtime.definition.DocumentParser.resolveEntity(DocumentParser.java:177)
    at org.apache.xerces.util.EntityResolverWrapper.resolveEntity(Unknown Source)
    at org.apache.xerces.impl.XMLEntityManager.resolveEntity(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.saxParsing(DocumentParser.java:158)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.parse(DocumentParser.java:123)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions(ClassLoaderWeavingAdaptor.java:272)
    at org.aspectj.weaver.loadtime.DefaultWeavingContext.getDefinitions(DefaultWeavingContext.java:130)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize(ClassLoaderWeavingAdaptor.java:156)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.initialize(Aj.java:340)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.getWeavingAdaptor(Aj.java:345)
    at org.aspectj.weaver.loadtime.Aj$WeaverContainer.getWeaver(Aj.java:319)
    at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:113)
    at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:54)
    at sun.instrument.TransformerManager.transform(Unknown Source)
    at sun.instrument.InstrumentationImpl.transform(Unknown Source)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

I want to fix this error


Answer:

Well, you have several strange issues and errors in your project:

  1. Obviously your POJO application does not use Spring. So you can get rid of Spring dependencies and also of spring-instrument.jar on your command line. You also do not need core-context.xml.
  2. Xerces is also not needed as far as I can see.
  3. If you use aspectjweaver.jar as a dependency, aspectjrt.jar is superfluous because the former is a superset and thus contains the latter.
  4. In aop.xml there is a package name typo: Please use com.mkyong in the aspect name, not com.mykong. Otherwise the aspect will never be found.
  5. In your include within tag you should use .. syntax in order to in-/exclude also subpackages.
  6. Your aspect class is a total mess:

    • You use nested classes for no apparent reason.
    • You use @Around, but JoinPoint instead of ProceedingJoinPoint in the advice signature.
    • You use @Around, but never call proceed().

So how about this?

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mkyong</groupId>
  <artifactId>NumberGenerator</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>NumberGenerator</name>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.10</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="com.mkyong.MyAspect"/>
  </aspects>
  <weaver options="-verbose -showWeaveInfo">
    <include within="com.mkyong..*"/>
    <exclude within="org.jibx*..*"/>
  </weaver>
</aspectj>

Aspect:

package com.mkyong;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
  @Around("execution(!static * *(..))")
  public Object dontLogDuplicates(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    System.out.println(thisJoinPoint);
    return thisJoinPoint.proceed();
  }
}

Console log:

I see the following when adding -javaagent:/path/to/aspectjweaver.jar to my JUnit run configuration in IntelliJ IDEA:

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.8.10 built on Monday Dec 12, 2016 at 19:07:48 GMT
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info using configuration /C:/Users/Alexander/Documents/java-src/yami12376-AspectJ/target/classes/META-INF/aop.xml
[AppClassLoader@18b4aac2] info register aspect com.mkyong.MyAspect
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(void com.mkyong.AppTest.testLengthOfTheUniqueKey())' in Type 'com.mkyong.AppTest' (AppTest.java:9) advised by around advice from 'com.mkyong.MyAspect' (MyAspect.java)
execution(void com.mkyong.AppTest.testLengthOfTheUniqueKey())
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(java.lang.String com.mkyong.App.generateUniqueKey())' in Type 'com.mkyong.App' (App.java:12) advised by around advice from 'com.mkyong.MyAspect' (MyAspect.java)
execution(String com.mkyong.App.generateUniqueKey())

But really, you should fix your POM and make sure that aspect weaving is done from there and not manually. It is really ugly like this.

Update: After all the criticism, let me also say one positive thing: You provided a MCVE, thanks for that. With code fragments, questions and answers we would never have found the many bugs in your files. So it was a smart and prudent decision to create the GitHub project. I could easily spot the problems. :-) If everyone did that, I would save a lot of time here.

Question:

We have a large code base that was developed in Spring MVC. The following code repeats all over the place.

 public @ResponseBody BaseResponse<String> getSomething() {
    BaseResponse<String> response = new BaseResponse<String>();
    try {
        //something
    } catch (Exception e) {
        BaseError be = ExceptionHandler.errorResponse(e);
        response.setError(be);
    }
    return response;
}

I am curious if this can be refactored or simplified using aspects?

ie: ExceptionHandler can be called within the aspect but how about setting the error in response?

Thanks.


Answer:

I recreated your situation with plain Java + native AspectJ because I am not a Spring user. But the aspect as such and its pointcut should be the same in Spring AOP, only the aspect also needs to be a @Component.

Several dummy classes:

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResponseBody {}
package de.scrum_master.app;

public class BaseError {
    private Exception e;

    public BaseError(Exception e) {
        this.e= e;
    }

    public String getMessage() {
        return e.getMessage();
    }
}
package de.scrum_master.app;

public class ExceptionHandler {
    public static BaseError errorResponse(Exception e) {
        return new BaseError(e);
    }
}
package de.scrum_master.app;

public class BaseResponse<T> {
    private String body;
    private String error = "OK";

    public void setBody(String body) {
        this.body = body;
    }

    public void setError(BaseError be) {
        error = be.getMessage();
    }

    @Override
    public String toString() {
        return "BaseResponse [body=" + body + ", error=" + error + "]";
    }
}

Driver application:

There are two target methods returning BaseResponse<String>, basically doing the same as your sample method, throwing exceptions randomly, but with exception handling stripped off. I guess this is what you want to achieve.

There also is anoter method not to be targeted by the aspect (as a negative test case).

package de.scrum_master.app;

import java.util.Random;

public class Application {
    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        Application application = new Application();
        for (int i = 0; i < 5; i++) {
            System.out.println(application.doSomething());
            System.out.println(application.getSomething());
            System.out.println(application.getSomethingElse());
        }
    }

    public String doSomething() {
        return "Doing something";
    }

    public @ResponseBody BaseResponse<String> getSomething() {
        BaseResponse<String> response = new BaseResponse<String>();
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot get something");
        response.setBody("getting something");
        return response;
    }

    public @ResponseBody BaseResponse<String> getSomethingElse() {
        BaseResponse<String> response = new BaseResponse<String>();
        if (RANDOM.nextBoolean())
            throw new RuntimeException("cannot get something else");
        response.setBody("getting something else");
        return response;
    }
}

Error handling aspect:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import de.scrum_master.app.BaseError;
import de.scrum_master.app.BaseResponse;
import de.scrum_master.app.ExceptionHandler;

@Aspect
public class ErrorHandler {
    @Around("execution(de.scrum_master.app.BaseResponse<String> *(..))")
    public Object handleError(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        //System.out.println(thisJoinPoint);
        try {
            return thisJoinPoint.proceed();
        } catch (Exception e) {
            BaseError be = ExceptionHandler.errorResponse(e);
            BaseResponse<String> response = new BaseResponse<String>();
            response.setBody("uh-oh!");
            response.setError(be);
            return response;
        }
    }
}

Console log:

Here you can see nicely how each BaseResponse is either created and populated by cour application code or by the error handling aspect:

Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]
Doing something
BaseResponse [body=uh-oh!, error=cannot get something]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]

Question:

I'm trying to use FasterXML Jackson-Databind in order to load configuration from a JSON file.

My application uses AspectJ. Aspect J is loaded via the following command line switch: "-javaagent:target\aspectjweaver-1.6.12.jar".

When I try to load the configuration without starting AspectJ, everything works as usual.

When I try to load the configuration with AspectJ, I get the following error stack:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.reflect.Proxy.newInstance(Proxy.java:717)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:708)
    at sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:239)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:229)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
    at java.lang.Class.initAnnotationsIfNecessary(Class.java:3079)
    at java.lang.Class.getAnnotation(Class.java:3038)
    at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:113)
    at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:66)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:202)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
    at java.lang.Class.initAnnotationsIfNecessary(Class.java:3079)
    at java.lang.Class.getAnnotation(Class.java:3038)
    at com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std.<clinit>(VisibilityChecker.java:170)
    at com.fasterxml.jackson.databind.ObjectMapper.<clinit>(ObjectMapper.java:261)
    at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
    at com.mytest.core.ConfigurationManager.getOrLoadConfigurationData(ConfigurationManager.java:33)
    at com.mytest.core.ApplicationContext.getConfigruation(ApplicationContext.java:51)
    at com.mytest.core.services.FootprintsServiceClient.init(FootprintsServiceClient.java:43)
    at com.mytest.core.AppManager.init(AppManager.java:43)
    at com.mytest.core.AppManager.getInstance(AppManager.java:61)
    at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
    at io.demo.App.main(App.java:12)
Caused by: java.lang.NullPointerException
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:530)
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:448)
        at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
        at com.mytest.core.ConfigurationManager.getOrLoadConfigurationData(ConfigurationManager.java:33)
        at com.mytest.core.ApplicationContext.getConfigruation(ApplicationContext.java:51)
        at com.mytest.core.services.FootprintsServiceClient.init(FootprintsServiceClient.java:43)
        at com.mytest.core.AppManager.init(AppManager.java:43)
        at com.mytest.core.AppManager.getInstance(AppManager.java:61)
        at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
        at com.sun.proxy.$Proxy3.<clinit>(Unknown Source)
        ... 29 more

I'll appreciate if you could point me to the root cause or to a recommended debugging technique.

Kind regards,

Nadav

EDIT Please note that I know what's null pointer is. My problem is that I'm getting NullPointerException from an instance of the ObjectMapper class, which is part of the Jackson framework.


Answer:

Your annotation processor is re-entering itself. If you look through the stack trace from main upwards, you see:

at io.demo.App.main(App.java:12)
at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
at com.mytest.core.AppManager.getInstance(AppManager.java:61)

which starts to load Jackson

at com.fasterxml.jackson.databind.ObjectMapper.<clinit>(ObjectMapper.java:261)
at com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std.<clinit>(VisibilityChecker.java:170)
at java.lang.Class.getAnnotation(Class.java:3038)

VisibilityChecker line 170 has a static intialisation to load the annotations on the Std class, so this goes back into reflection and eventually:

at sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:239)

creates a proxy (implementation of an annotation?), which during class initialisation tries to go through an aspect again:

    at com.sun.proxy.$Proxy3.<clinit>(Unknown Source)
    at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
    at com.mytest.core.AppManager.getInstance(AppManager.java:61)

and now we're back at AppManager.getInstance, line 61

    at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
    at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:448)

and this is trying to construct an ObjectMapper before the ObjectMapper class initialisation has completed- which not surprisingly, causes an error.

I don't have a solution (as I'm not familiar enough with AspectJ), but that's the core of what's happening. Possibly something like setting a flag to indicate if the configuration is unloaded/loading/loaded, and avoiding trying to re-enter the configuration load while the configuration is actually loading.

Question:

I have 2 aspects that are applied on the same method. When the method executes correctly I have no problem, everything is working fine and both aspects work as expected. The problem is when the method throw an exception. In these cases, the first aspect re-throw correctly the exception, but the second aspect is generating a nullpointerexception. I was able to reproduce the problem isolating the case on a unit test in a separated project. Those are the aspects (actually I removed all the logic, at the moment they do nothing):

@Aspect
public class LogContextConstantAspect {

    @Around("execution(* *(..)) && @annotation(logContextConstant)")
    public Object aroundMethod(ProceedingJoinPoint joinPoint, LogContextConstant logContextConstant) throws Throwable {
        try {
            Object res = joinPoint.proceed();
            return res;
        } catch (Throwable e) {
            throw e;
        }
    }
}

and

@Aspect
public class LogExecutionTimeAspect {

    @Around("execution(* *(..)) && @annotation(logExecutionTime)")
    public Object around(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
        try {
            Object res = joinPoint.proceed();
            return res;
        } catch (Throwable e) {
            throw e;
        }
    }
}

while those are the 2 custom annotation that I implemented

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {

    String paramKey() default "execution_time";
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface LogContextConstant {

    String name();

    String value();
}

then I created a simple class with the following methods

public class AspectSimple {

    public int execute() {
        System.out.println("ok");
        return 1;
    }

    public int failSimple() throws CustomException {
        throw new CustomException("ko");
    }

    @LogExecutionTime
    public int failWithAspect1() throws CustomException {
        throw new CustomException("ko");
    }   

    @LogContextConstant(name="test", value = "test")
    public int failWithAspect2() throws CustomException {
        throw new CustomException("ko");
    }   


    @LogExecutionTime
    @LogContextConstant(name="test", value = "test")
    public int executeWithAspect() {
        return 1;
    }

    @LogExecutionTime
    @LogContextConstant(name="test", value = "test")
    public int failWithAspect3() throws CustomException {
        throw new CustomException("ko");
    }   
}

and finally this unit test

public class TestSample {

    static AspectSimple as = null;

    @BeforeAll
    public static void setup() {
        as = new AspectSimple();
    }

    @Test
    public void test1() {
        int res = as.execute();
        assertEquals(1, res);
    }

    @Test
    public void test2() {
        int res = as.executeWithAspect();
        assertEquals(1, res);
    }

    @Test
    public void test3() {
        try {
            int res = as.failSimple();
        } catch (CustomException e) {
            assertNotNull(e); 
        } catch (Exception e) {
            fail();
        }
    }   

    @Test
    public void test4() {
        try {
            int res = as.failWithAspect1();
        } catch (CustomException e) {
            assertNotNull(e); 
        } catch (Exception e) {
            fail();
        }
    }       

    @Test
    public void test5() {
        try {
            int res = as.failWithAspect2();
        } catch (CustomException e) {
            assertNotNull(e); 
        } catch (Exception e) {
            fail();
        }
    }       

    @Test
    public void test6() {
        try {
            int res = as.failWithAspect3();
        } catch (CustomException e) {
            assertNotNull(e); 
        } catch (Exception e) {
            fail();
        }
    }       

}

All tests are running correctly, only the last one (test6) fails.

the application is running on java 8, with aspectj 1.9.4 and junit 5. Here the complete pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>it.pivimarco.samples.aspects</groupId>
    <artifactId>aspect-sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-engine</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-commons</artifactId>
            <version>1.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <version>5.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.5.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.4</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>
                                        org.baeldung.executable.ExecutableMavenJar
                                    </mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.0</version>
                <executions>
                    <execution>
                        <id>default-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <includes>
                                <include>**/Test*.java</include>
                                <include>**/*Test.java</include>
                                <include>**/*Tests.java</include>
                                <include>**/*TestCase.java</include>
                            </includes>
                            <properties>
                                <excludeTags>slow</excludeTags>
                            </properties>
                            <forkCount>1</forkCount>
                            <reuseForks>false</reuseForks>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <includes>
                        <include>**/Test*.java</include>
                        <include>**/*Test.java</include>
                        <include>**/*Tests.java</include>
                        <include>**/*TestCase.java</include>
                    </includes>
                    <properties>
                        <excludeTags>slow</excludeTags>
                    </properties>
                    <forkCount>1</forkCount>
                    <reuseForks>false</reuseForks>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <target>1.8</target>
                    <source>1.8</source>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.11</version>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.9.4</version>
                        <scope>compile</scope>
                    </dependency>
                </dependencies>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <proc>none</proc>
                    <complianceLevel>1.8</complianceLevel>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

If I apply just a single aspect the CustomException is throwed as aspected, but when both aspects are applied I'm getting a nullpointerexception.

I've also tried to declare the precedence of the aspects, using DeclarePrecedence annotation, but it didn't work

@DeclarePrecedence("it.pivimarco.samples.aspects.LogContextConstantAspect,it.pivimarco.samples.aspects.LogExecutionTimeAspect")

This is the stacktrace of the NPE

java.lang.NullPointerException
    at it.pivimarco.samples.aspects.AspectSimple.failWithAspect3_aroundBody10(AspectSimple.java:35)
    at it.pivimarco.samples.aspects.AspectSimple$AjcClosure11.run(AspectSimple.java:1)
    at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:170)
    at it.pivimarco.samples.aspects.LogContextConstantAspect.aroundMethod(LogContextConstantAspect.java:18)
    at it.pivimarco.samples.aspects.AspectSimple.failWithAspect3(AspectSimple.java:35)
    at it.pivimarco.samples.aspects.TestSample.test6(TestSample.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

Answer:

I think you uncovered a bug in the AspectJ compiler (versions 1.9.3, 1.9.4) which does not occur in version 1.9.2, as I said in my comment. I have just created AspectJ bug ticket #552687 on your behalf. Please check there for further updates. For now you can just downgrade to 1.9.2 and continue working.


Update: AspectJ 1.9.5 with the bugfix is out. Please try again. My retest was successful.

Question:

I have a Spring MVC application using Spring 4.1.0. Part of my code is generated (by MyEclipse), and since I periodically have to regenerate it due to DB changes, I chose to use aspects to add methods and properties to the generated classes without losing my customizations with each regeneration.

Recently I decided to get rid of Eclipse building, and wanted to use Maven instead. I got myself a Bamboo server, found out all the dependencies I needed, and the build seems to complete fine. However, when I deploy to tomcat the WAR I made using maven, I have a problem: the methods I am adding with aspects are not able to catch their own raised exceptions. For example, here's an aspect I am using to add a method to a generated class:

public Elementvalue ElementvalueDAOOligoExtension.getDrawdownRecoveryPeriod(Integer elementid, java.util.Calendar date, Double value, Integer elementvalueid, int startResult, int maxRows) throws DataAccessException {
    try {
        Query query = createNamedQuery("getDrawdownRecoveryPeriod", startResult, maxRows, elementid, date, value, elementvalueid);
        return (ch.oligofunds.oligoworld.domain.Elementvalue) query.getSingleResult();
    } catch (NoResultException nre) {
        return null;
    }
}

As you see, the idea is that if I get no results for the query, I return null (which is then treated properly by the caller). However, when this method is called, the NoResultException actually bubbles up to the caller, and I can find it in the logs:

    org.springframework.dao.EmptyResultDataAccessException: No entity found for query; nested exception is javax.persistence.NoResultException: No entity found for query
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:392)
    at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:33)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.getDrawdownRecoveryPeriod_aroundBody20(ElementvalueDAOImplAspect.aj:145)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect$AjcClosure21.run(ElementvalueDAOImplAspect.aj:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethod$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj:141)
    at ch.oligofunds.oligoworld.dao.ElementvalueDAOImpl.getDrawdownRecoveryPeriod(ElementvalueDAOImpl.java:1)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethodDispatch1$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.getDrawdownRecoveryPeriod_aroundBody18(ElementvalueDAOImplAspect.aj:137)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect$AjcClosure19.run(ElementvalueDAOImplAspect.aj:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethod$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj:136)
    at ch.oligofunds.oligoworld.dao.ElementvalueDAOImpl.getDrawdownRecoveryPeriod(ElementvalueDAOImpl.java:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    ...

The fourth-to-last line points to the line of code above where I return the single result of the query. So, I would expect that a NoResultException at that point would be caught by the catch section, which apparently does not happen.

I should point out that everything works fine when I build in Eclipse. So I suppose there's some fundamental difference in how eclipse builds this and how standalone maven with aspectj-maven-plugin manages things (which is also hinted by the fact that standalone maven creates a bunch of $AjcClosureXXX.class files, which are not present if I build with Eclipse).

Anybody can offer a pointer in the right direction? Am I fundamentally misunderstanding about the way maven is building this code with respect to how Eclipse does it?


Answer:

What you're seeing is Spring's JpaExceptionTranslatorAspect from spring-aspects in action. It wraps call sites to methods of EntityManager, EntityManagerFactory, EntityTransaction and Query, and converts exceptions raised in those method calls and wraps them with a Spring specific DataAccessException subtype if possible.

The difference between your Eclipse based build and your Maven build is most likely that your Eclipse build uses the Java compiler while your Maven build is using either the AspectJ compiler or the Java compiler and AspectJ weaver. So the Spring JpaExceptionTranslatorAspect does take effect in your Maven based build but not in your Eclipse based build.

Try catching the Spring specific wrapper EmptyResultDataAccessException instead of NoResultException or disable the JpaExceptionTranslatorAspect so your JPA exceptions don't get converted.

Also, you should install the AJDT (AspectJ Development Tools) plugin into Eclipse and configure your projects to use the AspectJ compiler instead of the Java compiler so that your Eclipse and Maven build are the same.

Question:

I have been using metrics-aspectj library and found it very convenient to annotate a method to capture performance metrics. Recently I hit the wall when trying the extend a class that has annotated methods. Here's what I see:

@Metrics
public class Base {
    public void something_not_timed() {
        ...
    }

    @Timed(name="method1-ProcessTime")
    public void method1() {
       ...
    }
}

I have been using Base class in production without issue. Now I need to extend this class.

public class Derived extends Base {
    @Override
    public void something_not_timed() {
        ....
    }
}

As you can see, method1() is not overridden. But the problem is that whenever I use method1() in Derived class, I would get a NullPointerException in method1_aroundBody1$advice().

I'm not familiar with AspectJ so couldn't really figure out what I'm missing, any advice will be highly appreciated.

Thanks!

Regards, Cary


Answer:

It is a bug in metrics-aspectj. You have opened a ticket for it anyway, I noticed. I have created a little demontration repository for the problem and described it in more detail in my answer to your GitHub ticket.

Question:

I have an error when I use AspectJ:

Controller:

@RequestMapping("/logout")
public ModelAndView Logout(
    Locale locale,
    Model model,
    HttpServletRequest request
) throws ParseException {
    NguoiDung student = new NguoiDung();
    student = (NguoiDung) request.getSession().getAttribute("customer");
    String email = student.getEmail();
    dangxuat(email);
    request.getSession().removeAttribute("chuyentrang");
    request.getSession().removeAttribute("nguoidung");
    request.getSession().removeAttribute("customer");
    return new ModelAndView("login");
}

Class LoggingAspectJ

public aspect LoggingAspectJ {
    pointcut callLogout(String email) :
        call(* StudentController.dangxuat(String)) &&
        args(email) && 
        within(StudentController);

    after(String email) : callLogout(email) {
        System.out.println("Logout");
    }
}

When I choose Logout, I got the following error:

type

Exception report

message

Handler processing failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/NoAspectBoundException

description

The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Handler
processing failed; nested exception is java.lang.NoClassDefFoundError:
org/aspectj/lang/NoAspectBoundException
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.NoClassDefFoundError:
org/aspectj/lang/NoAspectBoundException
    com.joseph.controller.StudentController.Logout(StudentController.java:124)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.ClassNotFoundException:
org.aspectj.lang.NoAspectBoundException
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
    com.joseph.controller.StudentController.Logout(StudentController.java:124)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

Answer:

The AspectJ runtime library aspectjrt.jar (maybe the name also includes a version number, depending on where you get the library from) must be on the classpath. Obviously it is not.

Question:

After following an AWS tutorial for Eclipse, my code no longer compiles and runs. I decided to undo what the tutorial told me, so I may have changed some settings that I forgot to unchanged but I really cannot find the root of my problem. Eclipse seems to be back to its default settings now but I still can't run a very simple class. I get this error:

Exception in thread "main" java.lang.NoClassDefFoundError: /Users/myname/aspectj1/6/lib/aspectjrt/jar
Caused by: java.lang.ClassNotFoundException: .Users.myname.aspectj1.6.lib.aspectjrt.jar
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

Answer:

It seems that your Eclipse doesn't found the library of aspectj. Try to download it again from:

https://eclipse.org/aspectj/downloads.php

By your stack trace I suppose that the version of aspectj that it is looking for it's the 1.6 so I suppose that you have to search the package in which puts aspectj-1.6.0.jar in the webpage that I put above.

EDIT: Look at these lines in the tutorial that you put above:

Certain AWS Flow Framework for Java annotations such as @Asynchronous require AspectJ. You don't need to use AspectJ directly, but you must enable it with either load-time weaving or compile-time weaving.

It seems that it is necesary for AWS to the correct performance so I think you have to download the libraries of aspectj again.

I expect it will solve your problem!

Question:

Currently, my application server does not start because it reports class not found when my dependencies are already exposed in the maven and bundled together in my ear.

Basically how do you get JBOSS 7.1 to work with AspectJ smoothly.

Maybe I need to add a module? An AspectJ module?

Any advice will be great.

More Details about the error

01:18:41,515 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (MSC service thread 1-7) Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener: java.lang.NoClassDefFoundError: org/aspectj/weaver/BCException
    at java.lang.Class.getDeclaredMethods0(Native Method) [rt.jar:1.7.0_45]
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2531) [rt.jar:1.7.0_45]
    at java.lang.Class.getDeclaredMethods(Class.java:1855) [rt.jar:1.7.0_45]
    at org.springframework.core.type.StandardAnnotationMetadata.hasAnnotatedMethods(StandardAnnotationMetadata.java:159) [spring-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]

Answer:

Since my app server is loaded with a predefined list of modules from Spring. I had to override it with my own.

An example is shown below.

<module xmlns="urn:jboss:module:1.1" name="org.springframework.spring">

<resources>
    <resource-root path="spring-aop-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-asm-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-beans-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-context-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-core-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-expression-3.1.1.RELEASE.jar"/>
    <resource-root path="spring-web-3.1.1.RELEASE.jar"/>
    <resource-root path="aopalliance-1.0.jar"/> <!-- added -->
    <resource-root path="cglib-nodep-2.2.2.jar"/> <!-- added --> 
    <resource-root path="aspectjrt-1.6.11.jar"/> <!-- added -->
    <resource-root path="aspectjweaver-1.6.11.jar"/> <!-- added -->
</resources>

<dependencies>
   ...
</dependencies>

</module>

Question:

I have a api.jar with some entities compiled with Spring Roo. I use this library from my android application and see following for every roo generated entity:

E/dalvikvm(10938): Could not find class 'org.aspectj.lang.NoAspectBoundException', referenced from method _Roo_Json.aspectOf W/dalvikvm(10938): VFY: unable to resolve new-instance 2010 (Lorg/aspectj/lang/NoAspectBoundException;) in L_Roo_Json;

I searched at stackoverflow and found only one answer and it didn't help (suggested to add a aspectjrt).

Does anybody has a clue what does it means?


Answer:

As Spring-Roo uses AspctJ ITD to generate code you need add its runtime libraries as a dependency. But I think that AspectJ is not suitable for Android. It works

I found android-aspectj library which seems to be a possible way to archive this (I don't try it). Also, this library refers to a post which explains it.

Good luck!