Hot questions for Using AspectJ in proxy

Question:

I am learning Spring (currently its AOP framework). Even though all sources I've read say that to enable AOP one needs to use @EnableAspectJAutoProxy annotation (or its XML counterpart) my code seems to work with annotation commented out. Is that because I use Lombok or Spring Boot (v. 1.5.9.RELEASE, dependent on Spring v. 4.3.13.RELEASE)?

Minimal example follows:

build.gradle

buildscript {
    ext {
        springBootVersion = '1.5.9.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

group = 'lukeg'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter')
    compileOnly('org.projectlombok:lombok')
    compile("org.aspectj:aspectjweaver:1.8.11")
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

ApplicationConfiguration.java (note the AOP annotation is commented out)

package lukeg;

import org.springframework.context.annotation.*;

@Configuration
@ComponentScan
//@EnableAspectJAutoProxy
public class ApplicationConfiguration {
    @Bean
    TestComponent testComponent() {
        return new TestComponent();
    }
}

LearnApplication.java

package lukeg;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class LearnApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(LearnApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
        TestComponent testComponent = context.getBean(TestComponent.class);
        System.out.println(""+testComponent);
    }
}

LoggerHogger.java

package lukeg;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LoggerHogger {

    @Pointcut("execution(* lukeg*.*.toString(..))")
    public void logToString() {}

    @Before("logToString()")
    public void beforeToString () {
        System.out.println("Before toString");
    }
}

TestComponent.java

package lukeg;

import lombok.Data;


@Data
public class TestComponent {
}

Answer:

The @SpringBootApplication annotation contains the @EnableAutoConfiguration annotation. This autoconfiguration is one of the attractions of Spring Boot and makes configuration simpler. The auto configuration uses @Conditional type annotations (like @ConditionalOnClass and @ConditionalOnProperty) to scan the classpath and look for key classes that trigger the loading of 'modules' like AOP.

Here is an example AopAutoConfiguration.java

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.Advice;
import org.aspectj.weaver.AnnotatedElement;

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
    AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass = false)
  @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
  public static class JdkDynamicAutoProxyConfiguration {

  }

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass = true)
  @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
  public static class CglibAutoProxyConfiguration {

  }

}

As you can see, if you add one of the above aop classes to your class path (or property), Spring will detect it and effectively behave as if you had the @EnableAspectJAutoProxy annotation on your main class.

Your project has a file LoggerHogger which has an @Aspect.

Question:

I am using Spring Boot, and I would like to use AspectJ with it.

The following works (of course):

@Aspect
@Component
public class RequestMappingAspect {

    @Before("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void advice(JoinPoint joinPoint) {
        ...
    }
}

However, if @Component is removed and @EnableAspectJAutoProxy is added, the following does not work.

@SpringBootApplication
@EnableSwagger2
@EnableAspectJAutoProxy
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

How to enable AspectJ auto proxy correctly?


Answer:

You need both @EnableAspectJAutoProxy for the spring configuration and combination of @Aspect / @Component annotations

@EnableAspectJAutoProxy does the same thing as xml based <aop:aspectj-autoproxy>

Question:

I created sample Spring-boot application and it works fine without any error,

now I want to practice spring-retry to retry some of the methods. If i don't use @EnableRetry my application starts without any errors but retry is not working.

If I use @EnableRetry on config class my application failed to start

build.gradle

apply plugin: 'java-library'

repositories {
  jcenter()
  }

 dependencies {

        // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
         compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.0.RELEASE'
        // https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka
         compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.2.0.RELEASE'
        // https://mvnrepository.com/artifact/commons-logging/commons-logging
         compile group: 'commons-logging', name: 'commons-logging', version: '1.2'
         // https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
         compile group: 'org.springframework.retry', name: 'spring-retry', version: '1.2.0.RELEASE'

}

Config

import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;

@Configuration
@EnableRetry
public class RetryConfig {

 }

retry service

@Service
public class RetryService {

 @Retryable(value = { CustomException.class },  maxAttempts = 2, backoff = @Backoff(delay=1000))
 public Optional<String> requestOne(int value){
    if(value ==1) {
        throw new CustomException();
    }
    return Optional.of(" request one method");
}

@Retryable(value = { CustomException.class },  maxAttempts = 2, backoff = @Backoff(delay=1000))
public Optional<Integer> requestTwo(int value){
    if(value ==1) {
        throw new CustomException();
    }
    return Optional.of(1);
}

@Recover
public Optional<String> recovery(CustomException ex, int value){
    return Optional.of(" recovery method ");
  }

}

ERROR

2018-12-09 22:56:18.951  WARN 32113 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Pointcut
2018-12-09 22:56:18.961  INFO 32113 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
 2018-12-09 22:56:18.968 ERROR 32113 --- [           main] o.s.boot.SpringApplication               : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Pointcut
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:584) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:228) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:707) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at com.mtpc.MtpcMain.main(MtpcMain.java:10) [bin/:na]
 Caused by: java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Pointcut
at org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.<clinit>(AbstractAspectJAdvisorFactory.java:62) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.initBeanFactory(AnnotationAwareAspectJAutoProxyCreator.java:82) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.setBeanFactory(AbstractAdvisorAutoProxyCreator.java:63) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1767) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1732) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 15 common frames omitted

 Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.annotation.Pointcut
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_191]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_191]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_191]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_191]
... 21 common frames omitted

Answer:

Retry expect aspect dependencies which be solved using 2 solutions:

including spring-boot-starter-aop solved this for me and ensured versioning compatibility with the rest of Spring Boot.

Or

add the following dependency into my pom:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
</dependency>

Question:

According this answer https://stackoverflow.com/a/3429757/2674303 To use @Transactional when I execute local method I did following steps:

added to pom.xml:

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.7</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>

replace in context

<tx:annotation-driven transaction-manager="transactionManager"/>

with

<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

after it I saw

Could not obtain transaction-synchronized Session for current thread

additionally added:

<context:load-time-weaver/>

But when make mvn clean install I see(problem occures when tests try to execute. In my test I up appliction context):

    java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    ....
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.weaving.AspectJWeavingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)

    ... 31 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)

    ... 45 more
Caused by: java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
    at org.springframework.context.weaving.DefaultContextLoadTimeWeaver.setBeanClassLoader(DefaultContextLoadTimeWeaver.java:91)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1590)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1561)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 54 more
update

entire 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.terminal</groupId>
    <artifactId>terminal-company</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>terminal-company</name>


    <properties>
        <spring.version>4.1.6.RELEASE</spring.version>
        <spring.security.version>3.2.4.RELEASE</spring.security.version>
        <org.slf4j-version>1.5.10</org.slf4j-version>
        <jetty.version>9.2.5.v20141112</jetty.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-bom</artifactId>
                <version>${spring.security.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2</version>
        </dependency>

        <!-- Data -->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.0-801.jdbc4</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.182</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.0.GA</version>
        </dependency>

        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
        </dependency>
        <!-- Integration-->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-http</artifactId>
            <version>${spring.version}</version>
        </dependency>


        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.1.3.Final</version>
        </dependency>

        <!-- logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>

        <!-- JSON -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.12</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20140107</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>1.7.1</version>
        </dependency>

        <!-- Commons -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.0.2</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- Test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>


        <!-- other -->
        <dependency>
            <groupId>org.imgscalr</groupId>
            <artifactId>imgscalr-lib</artifactId>
            <version>4.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.pmd</groupId>
            <artifactId>pmd-jsp</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.pmd</groupId>
            <artifactId>pmd-core</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.pmd</groupId>
            <artifactId>pmd-java</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>xml-apis</groupId>
            <artifactId>xml-apis</artifactId>
            <version>1.4.01</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-core</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>net.bull.javamelody</groupId>
            <artifactId>javamelody-core</artifactId>
            <version>1.56.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.7</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>terminal-company</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <includeTests>true</includeTests>
                    <printFailingErrors>true</printFailingErrors>
                    <verbose>true</verbose>
                    <rulesets>
                        <ruleset>rulesets/java/basic.xml</ruleset>
                        <ruleset>rulesets/java/braces.xml</ruleset>
                        <ruleset>rulesets/java/unusedcode.xml</ruleset>
                        <!--<ruleset>rulesets/java/codesize.xml</ruleset>-->
                        <ruleset>rulesets/java/imports.xml</ruleset>
                        <ruleset>rulesets/java/empty.xml</ruleset>
                        <ruleset>rulesets/jsp/basic.xml</ruleset>
                        <ruleset>ruleset-naming.xml</ruleset>
                    </rulesets>
                    <includes>
                        <include>**\/*.jsp</include>
                        <include>**\/*.java</include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <excludeFromFailureFile>${basedir}/src/main/resources/exclude-pmd.properties
                            </excludeFromFailureFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <warName>terminal-company</warName>
                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                    <webResources>
                        <resource>
                            <directory>${basedir}/src/main/resources/</directory>
                            <targetPath>/</targetPath>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
            <!-- IDE -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>tomcat-maven-plugin</artifactId>
                <version>1.1</version>
            </plugin>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>${jetty.version}</version>
                <configuration>
                    <webAppConfig>
                        <contextPath>/</contextPath>
                    </webAppConfig>
                    <httpConnector>
                        <port>8081</port>
                    </httpConnector>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>org.mortbay.jetty</groupId>
                                    <artifactId>jetty-runner</artifactId>
                                    <version>8.1.15.v20140411</version>
                                    <destFileName>jetty-runner.jar</destFileName>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-maven-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <url>jdbc:postgresql://127.0.0.1:5432/marc_db</url>
                    <user>marc</user>
                    <password>marc</password>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>9.4-1200-jdbc4</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>central</id>
            <name>Maven Repository Switchboard</name>
            <layout>default</layout>
            <url>http://repo1.maven.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-maven-release</id>
            <name>Spring Maven Release Repository</name>
            <url>http://maven.springframework.org/release</url>
        </repository>
        <repository>
            <id>spring-maven-milestone</id>
            <name>Spring Maven Milestone Repository</name>
            <url>http://maven.springframework.org/milestone</url>
        </repository>
        <repository>
            <id>JBoss Repo</id>
            <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
            <name>JBoss Repo</name>
        </repository>
        <repository>
            <id>codelds</id>
            <url>https://code.lds.org/nexus/content/groups/main-repo</url>
        </repository>
        <repository>
            <id>glassfish-repository</id>
            <url>http://download.java.net/maven/glassfish</url>
            <snapshots>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-maven-release</id>
            <name>Spring Maven Release Repository</name>
            <url>http://maven.springframework.org/release</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-maven-milestone</id>
            <name>Spring Maven Milestone Repository</name>
            <url>http://maven.springframework.org/milestone</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-roo-repository</id>
            <name>Spring Roo Repository</name>
            <url>http://spring-roo-repository.springsource.org/release</url>
        </pluginRepository>
        <pluginRepository>
            <id>central</id>
            <name>Maven Plugin Repository</name>
            <url>http://repo1.maven.org/maven2</url>
            <layout>default</layout>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <updatePolicy>never</updatePolicy>
            </releases>
        </pluginRepository>
    </pluginRepositories>
</project>
update 2:

If skip test phase while building application - build success and then run mvn clean install jetty:run I see following stacktrace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAspect': Post-processing failed of bean type [class org.springframework.transaction.aspectj.AnnotationTransactionAspect] failed; nested exception is java.lang.IllegalStateException: Failed to introspect annotations: protected abstract void org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$pointcut$$transactionalMethodExecution$e12(java.lang.Object)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:936)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)
    ...
Caused by: java.lang.IllegalStateException: Failed to introspect annotations: protected abstract void org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$pointcut$$transactionalMethodExecution$e12(java.lang.Object)
    at org.springframework.core.annotation.AnnotatedElementUtils.process(AnnotatedElementUtils.java:166)
    ... 69 more
Caused by: java.lang.IllegalAccessError: class sun.reflect.GeneratedConstructorAccessor14 cannot access its superclass sun.reflect.ConstructorAccessorImpl
    at sun.misc.Unsafe.defineClass(Native Method)
    at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
    ... 76 more
13.11.2015 04:57:35 ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAspect': Post-processing failed of bean type [class org.springframework.transaction.aspectj.AnnotationTransactionAspect] failed; nested exception is java.lang.IllegalStateException: Failed to introspect annotations: protected abstract void org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$pointcut$$transactionalMethodExecution$e12(java.lang.Object)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:936)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512)
    ...
Caused by: java.lang.IllegalStateException: Failed to introspect annotations: protected abstract void org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$pointcut$$transactionalMethodExecution$e12(java.lang.Object)
    at org.springframework.core.annotation.AnnotatedElementUtils.process(AnnotatedElementUtils.java:166)
    at org.springframework.core.annotation.AnnotatedElementUtils.getAnnotationAttributes(AnnotatedElementUtils.java:91) 
    ... 69 more
Caused by: java.lang.IllegalAccessError: class sun.reflect.GeneratedConstructorAccessor14 cannot access its superclass sun.reflect.ConstructorAccessorImpl
    at sun.misc.Unsafe.defineClass(Native Method)   
    ... 76 more
update 3

Also I tried to add

@Configuration
@EnableLoadTimeWeaving(aspectjWeaving= EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class Configiuration {

I see same result

update 4:

class which uses Transactional annotation:

@Service
@Transactional
public class CompanyServiceImpl implements CompanyService {
    @PostConstruct
    public void init() {
        this.refreshStopJobs();
    }
    ...
}   
Solution

Actually this post wa helpful for me


Answer:

Basically to make AspectJ Load Time Weaving to work you need at first think of environment your app is going to work. As the name says the "load time" means that your classes are going to be changed by classloader. So from your question I understand that you need yours LTW in two environment. First is the "Test" environment that is command line and second is the Servlet Container (Jetty/Tomcat).

So lets start from the Test Environment: Your tests are failing because classloader has no chance to edit/instrument/weave you classes, Spring can't help you as it isn't yet running and you have chosen Load Time over Run Time Weaving. So we need somehow tell the default classloader that we are going to hack to classes. This is documented at Spring Documentation To do so we need to add -javaagent which in our case instead of instrumenting/profiling runtime will just change the classes at load time. To achieve this just tell maven to add 2 javaaganets : the aspectj-weaver-x.jar and special spring-instrument-x.jar, so just in your maven plugins section add.

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.19</version>
        <configuration>
            <forkMode>once</forkMode>
            <argLine>
                    -javaagent:${settings.localRepository}/org/springframework/spring-instrument/4.2.2.RELEASE/spring-instrument-4.1.6.RELEASE.jar
                    -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/1.8.7/aspectjweaver-1.8.7.jar
            </argLine>
            <useSystemClassloader>true</useSystemClassloader>
        </configuration>
</plugin>

Just remember to add spring-instrument-4.1.6.RELEASE.jar as dependency at least in provided scope to be sure that it is in the repo ;) After adding this configuration settings you tests execution will work fine. Just try:

mvn clean package

Next lets start with the second environment the Servlet Container. If you are running Tomcat then you are happy, as you can overrride default classloader by the one which is shipped with spring by adding following META-INF/context.xml to your project.

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader
    loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>

More info here. For Jetty you should manually edit the run script and add two -javaagents as we have done for maven test environment.

Question:

I have a simple Spring Boot application with private @Scheduled method:

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Scheduled(fixedRate = 1000)
    private void scheduledTask() {
        System.out.println("Scheduled task");
    }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--<dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-spring-legacy</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
            <version>1.1.1</version>
        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.11</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

When micrometer dependencies and commented out everything works as expected, but when I uncomment them, following exception occurs:

Caused by: java.lang.IllegalStateException: Need to invoke method 'scheduledTask' found on proxy for target class 'DemoApplication' but cannot be delegated to target bean. Switch its visibility to package or protected.
    at org.springframework.aop.support.AopUtils.selectInvocableMethod(AopUtils.java:133) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:343) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:326) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1633) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    ... 15 common frames omitted

Does anyone have an idea what's going on underneath?

Edit: I think there is some kind of conflict between mictometer and aspectJ dependencies, the issue occurs only if both are present on classpath.


Answer:

Spring advice is usually implemented when possible with JDK proxies, which require an interface to implement dynamically (which does the interesting logic and then delegates to your business code). In a case like this, you have an actual class, so the best Spring can do is to subclass it.

However, there are two conflicting requirements here: Spring wants to apply advice that captures metrics for your code, but since the method is private, it isn't accessible from a subclass. (I'm actually moderately surprised it's detecting and calling your scheduled task with a private method.)

Changing your method to protected allows Spring to do this at runtime (not actual Java code, but the equivalent generated bytecode):

class DemoApplicationWithAdvice extends DemoApplication {
    @Override
    protected void scheduledTask() {
        // record start time
        super.scheduledTask();
        // write metric with execution time
    }
}

Question:

We're using GigaSpaces version 8.0.0 (yes it's old) along with Spring 3 (yes it's also old). There are two modules A and B. A is the "main" module that reads and writes to the space and exposes some remote services. A and B run separately. B creates an instance of an entity that has a field that is a class object. This class only exists in B; A does not know about it. It then makes a remote call to A that ends up writing the instance to the space.

Later, A loads up this entity and creates an instance of the remote class by doing entity.getClassObject().newInstance(). This works even though this class doesn't exist in the A's runtime classloader, because the classloader for this class is the LRMI (light remote-method invocation) classloader that comes with GigaSpaces. I guess it knows how to instantiate it.

The problem arose when we added an aspect to A. We have existing code that autowires an instance of the remote class using A's application context and also initializes it using initializeBean. The autowiring and initialization worked fine until we added the aspect. Now, during initialization, it attempts to see if the advices in the aspect apply to the bean that is being initialized. As part of this process, it attempts to create an instance of the class using Class.forName and the bean's class' name. This results in a ClassNotFoundException because the class obviously does not exist in the runtime class loader. So AspectJ resolves the type as MissingResolvedTypeWithKnownSignature instead of failing immediately. But eventually there is a failure when AspectJ tries to find the superclass of the class because it doesn't have that information, and it throws the following exception:

org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type com.mypackage.MyRemoteClass
 [Xlint:cantFindType]
        at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:129)
        at org.aspectj.weaver.Lint$Kind.signal(Lint.java:328)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.raiseCantFindType(MissingResolvedTypeWithKnownSignature.java:232)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.getDeclaredInterfaces(MissingResolvedTypeWithKnownSignature.java:86)
        at org.aspectj.weaver.ResolvedType.getDirectSupertypes(ResolvedType.java:82)
        at org.aspectj.weaver.patterns.TypePattern.matchesSubtypes(TypePattern.java:178)
        at org.aspectj.weaver.patterns.ExactTypePattern.matchesSubtypes(ExactTypePattern.java:74)
        at org.aspectj.weaver.patterns.TypePattern.matchesStatically(TypePattern.java:130)
        at org.aspectj.weaver.patterns.KindedPointcut.fastMatch(KindedPointcut.java:141)
        at org.aspectj.weaver.internal.tools.PointcutExpressionImpl.couldMatchJoinPointsInType(PointcutExpressionImpl.java:84)
        at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:238)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:200)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:254)
        at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:286)
        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:1426)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:386)
...

Is there any way around this? I can think of two approaches, but I'm not exactly sure how to go about it. One is to somehow prevent Spring from checking to see if the aspect applies, and the other is perhaps to swap out the runtime classloader with one that delegates to the LRMI classloader if it can't find a class in the runtime class loader. But I'm not sure if I can even get an instance of the LRMI classloader.

Has anyone run into this sort of issue?


Answer:

This is a known issue in the version of AspectJ that I was using (1.6.12). It appears to have been fixed in later versions -- at least since 1.8.14 (which is what I upgraded it to). So upgrading my version of AspectJ fixed this issue.

Question:

I am planning to use AspectJ's loadtime weaving feature for proxying in a Spring based web application. The three things (AFAIK) that are needed to get this working are:

  1. Set the proxying mode to "aspectj" (as opposed to "proxy")
  2. Add the spring-aspects and the aspectjweaver to the classpath
  3. Add the spring-instrument agent to the VM startup

My question was on the best practice on how to achieve #3. My causes of concern are:

  1. Since this is needed at application startup, I can't have it point to the spring-instrument jar in the WEB-INF/lib location of my webapp. I was thinking of having a static spring-instrument jar sitting in my CATALINA_HOME/lib that can be directly referred to.
  2. As the web application progresses, it might be the case that the spring version may be upgraded and we may forget to upgrade the version of the jar in CATALINA_HOME/lib.
  3. Many different applications may be using the same CATALINA_HOME and it is not always possible to have everyone upgrade the spring-instrument jar in lock-step fashion.

Since this problem seems to be like a generic one, I wanted to know from others how they address this concern.

Thanks!


Answer:

Depending on the container you don't need the spring-instrumentation.jar. A single <context:load-time-weaver /> in your configuration is enough.

You will need a recent version of Tomcat (version 8), Jetty, WebSphere, Weblogic or JBoss.

Question:

I am writing Spring MVC application which is deployed on tomcat. I want to add Spring AOP or AspectJ logger. So, I wrote a AspectLogger class:

@Aspect
@Service
class AspectLogger {

@Autowired
private MyLogger logger;

@Around("aop3()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    logger.debug("$$$$ AOP Something");
}

@Pointcut("execution(* com.dummy.DefController.*(..))")
public void aop3() {
}

And added to configuration annotation @EnableAspectJAutoProxy:

@Configuration
@ComponentScan("pl.mythesis.spring")
@EnableWebMvc
@EnableAspectJAutoProxy
public class SpringConfig extends WebMvcConfigurerAdapter

Dependencies in pom.xml file:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.1.4.RELEASE</version>
    </dependency>

And I obtained this exceptions:

    09-Jan-2016 17:17:48.970 SEVERE [http-apr-8080-exec-14] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultController' defined in file [C:\Users\Kasiek\S6IS\Praca Magisterska\MyThesisSite\SpringSite\target\SpringSite\WEB-INF\classes\pl\mythesis\spring\controller\DefaultController.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/core/annotation/OrderUtils
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4810)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:586)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:460)
    at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1583)
    at sun.reflect.GeneratedMethodAccessor67.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1460)
    at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:906)
    at org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:344)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:614)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: org/springframework/core/annotation/OrderUtils
    at org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory.getOrder(BeanFactoryAspectInstanceFactory.java:112)
    at org.springframework.aop.aspectj.annotation.LazySingletonAspectInstanceFactoryDecorator.getOrder(LazySingletonAspectInstanceFactoryDecorator.java:73)
    at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.getOrder(InstantiationModelAwarePointcutAdvisorImpl.java:159)
    at org.springframework.core.OrderComparator.getOrder(OrderComparator.java:71)
    at org.springframework.core.OrderComparator.compare(OrderComparator.java:58)
    at org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator.compare(AspectJPrecedenceComparator.java:81)
    at org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator.compare(AspectJPrecedenceComparator.java:49)
    at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder.compareTo(AspectJAwareAdvisorAutoProxyCreator.java:132)
    at org.aspectj.util.PartialOrder$SortObject.addDirectedLinks(PartialOrder.java:71)
    at org.aspectj.util.PartialOrder.addNewPartialComparable(PartialOrder.java:93)
    at org.aspectj.util.PartialOrder.sort(PartialOrder.java:129)
    at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.sortAdvisors(AspectJAwareAdvisorAutoProxyCreator.java:77)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:91)
    at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:69)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:330)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 55 more
Caused by: java.lang.ClassNotFoundException: org.springframework.core.annotation.OrderUtils
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1167)
    ... 74 more

Without annotation @EnableAspectJAutoProxy application is running properly, but I don't see "$$$$ AOP Something" in log.


Answer:

You need to upgrade your spring-core to the same version as spring-aop.

You are missing OrderUtils, see here in the api- this one is since 4.1, if you have 4.0.6, it won't be there.

Generally speaking, it's good to keep all your spring dependencies on the same version

Question:

I have an abstract class (database mapping) implementing an interface where default implementations are injected at runtime (this is part of another library and cannot be changed).

I want to override one of the default implementation via a proxy (as that seems like the way to override this).

public abstract class Table1 implements Storable<Table1>
{   
    @Sequence("ID_SEQUENCE")
    @Alias("ID")
    public abstract String getID();
    public abstract void setID(String ID);

    @Alias("NAME")
    public abstract String getAvailabilityZone();
    public abstract void setAvailabilityZone(String value);
}

public interface Storable<S extends Storable<S>> {
     //a bunch of method definition.
     boolean tryLoad() throws Exception;
}

Let's say I want to override tryLoad() method to do my own things instead of what the generated code provides. Given the nature of the library, it is not something I can achieve by simple @Override. The simple way this is currently used is as following:

public void method() {
        Table1 t = Repository.storageFor(Table1.class).prepare();
        t.setName( "temp" );
        if (!t.tryLoad())
           t.tryInsert();
}

I want to proxy tryLoad() without making changes in all the methods across the whole codebase - that would be to get proxied instance instead of actual one and perform the operation on that.

Is there any recommended way to achieve this?

Thanks!


Answer:

I woke up last night and felt bored, so despite your lack of feedback I created a little Carbonado showcase project and shared it on GitHub. I made three commits:

  1. Initial commit with Maven project already prepared for AspectJ and a JUnit test for me to find out how Carbonado actually works, because I had never used it before.

  2. Add failing unit test for behaviour of tryLoad() expected to be provided by aspect.

  3. Add aspect to make unit test pass. Aspect hooks into tryLoad() and auto-creates non-existent record. I do not know if I guessed right what you actually wanted to achieve, but if it was a different thing, just change the aspect implementation.

Sample code

Carbonado storable:

package de.scrum_master.app;

import com.amazon.carbonado.Nullable;
import com.amazon.carbonado.PrimaryKey;
import com.amazon.carbonado.Storable;

@PrimaryKey("ID")
public interface StoredMessage extends Storable<StoredMessage> {
  long getID();
  void setID(long id);
  @Nullable String getMessage();
  void setMessage(String message);
}

Aspect:

package de.scrum_master.aspect;

import com.amazon.carbonado.Storable;

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

@Aspect
public class CarbonadoAspect {
  @Around("call(boolean tryLoad()) && target(storable)")
  public boolean tryInsertIfNotFound(ProceedingJoinPoint thisJoinPoint, Storable storable) throws Throwable {
    System.out.println(thisJoinPoint);
    if ((boolean) thisJoinPoint.proceed())
      return true;
    System.out.println("Not found: " + storable + " -> inserting");
    return storable.tryInsert();
  }
}

JUnit test:

package de.scrum_master.app;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.amazon.carbonado.FetchException;
import com.amazon.carbonado.PersistException;
import com.amazon.carbonado.Repository;
import com.amazon.carbonado.RepositoryException;
import com.amazon.carbonado.Storage;
import com.amazon.carbonado.SupportException;
import com.amazon.carbonado.repo.map.MapRepositoryBuilder;

import de.scrum_master.app.StoredMessage;

public class CarbonadoTest {
  private Repository repo;
  private Storage<StoredMessage> storage;
  StoredMessage message;

  @Before
  public void setUp() throws Exception {
    repo = MapRepositoryBuilder.newRepository();
    storage = repo.storageFor(StoredMessage.class);
    message = storage.prepare();
  }

  @After
  public void tearDown() throws Exception {
    repo.close();
    repo = null;
    storage = null;
    message = null;
  }

  // (...)

  @Test
  public void aspectCreatesNonExistentRecord() throws SupportException, RepositoryException {
    message.setID(1);
    // Without the aspect this would be false
    assertTrue(message.tryLoad());
    assertEquals(message.getID(), 1);
    assertEquals(message.getMessage(), null);
  }

}

Enjoy!

Question:

I am new to spring and I found an interesting behavior but don't know how to fix it... I have a class as following:

@Component public class ScheduleService {

/** The Constant log. */
private static final Logger log = LoggerFactory.getLogger(ScheduleService.class);

/** The schedule repository. */
@Autowired
private ScheduleRepository  scheduleRepository;

@Autowired
private PipelineService pipelineService;


private AtomicReference     atomic_scheduler = new AtomicReference();

/**
 * Instantiates a new schedule service.
 */
public ScheduleService() {
}

/**
 * Starts the quarts scheduler instance
 * 
 */
public synchronized void start() {
    ....
}

public Scheduler getScheduler() {
    start();
    return (Scheduler) atomic_scheduler.get();
}

/**
 * Creates the schedule.
 *
 * @param session the session
 * @param schedule the Schedule
 * @return the Schedule
 */
public Schedule createSchedule(Session session, Schedule schedule) throws Exception {

.......... }

/**
 * Gets the Schedule.
 *
 * @param session the session
 * @param id the id
 * @return the Schedule
 */
@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED)
public Schedule getSchedule(Session session, String id) throws Exception {

..... }

/**
 * Gets the Schedule given the Schedule name.
 *
 * @param session the session
 * @param name the name of the Schedule to return
 * @return the Schedule
 */
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
public Schedule getScheduleByName(Session session, String name) throws Exception {
    ........
}

/**
 */
public Schedule updateSchedule(Session session, Schedule sch) throws Exception {

....... } }

I found all methods in this class are called by proxy but I don't know why... Should only "transactional" method be called by APO proxy? How do I solve this? I want non-transactional methods invoked by calling threads directly without going through proxy.

Thanks everyone for advise.


Answer:

Basically it is impossible to have only some of the methods called via proxy.

To implement the AOP behavior (in your case @Transactional) Spring has to build a proxy around your object so it can intercept invocations of the annotated methods. For this to work Spring must than inject the proxy instead of your object everywhere.

So every other object only knows the proxy. And all calls can only be made trough the proxy.

How should it be possible to have only the transactional calls go through the proxy? This would require quite a lot of byte code manipulation to find all calls to methods on your object and than start redirecting them somehow depending on if they are transactional. Also keep in mind that Spring does not only support singleton beans. With multiple instances of a class it must also figure out to witch object to delegate to. It is a lot easier to just inject the proxy everywhere and than let Java work normally from there.

If you want more details you might want to take a look at java.lang.reflect.Proxy and try building a proxy yourself. That would give you an idea how Java Dynamic Proxies actually work. (If I am not mistaken Spring also uses this class by default for its proxies.)

Question:

I am trying to execute a aspect on proxy object

package thispkg;

public class MyLogger {
    public void before() {
        System.out.println("=========Before========");
    }
    public void after() {
        System.out.println("=========After=========");
    }
    public void info() {
        System.out.println("=========Info=========");
    }
}

package thispkg;

public interface MyInterface {
    public void speak();
}

package thispkg;

public class MyInterfaceImpl implements MyInterface {
    @Override
    public void speak() {
        System.out.println("MyInterfaceImpl :: Hello world");
    }
}

package thispkg;

public class RandomClass {
    public void suvichar() {
        System.out.println("RandomClass (suvichar)::Karm kiye jaa, fal ki chinta mat kar");
    }
}

package thispkg;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("thispkg.xml");
        MyInterface in = (MyInterface) context.getBean("randomClass", RandomClass.class);
        in.speak();
    }
}

My XML

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

    <context:spring-configured/>
    <bean id="mylogger" class="thispkg.MyLogger"/>
    <bean id="randomClass" class="thispkg.RandomClass"/>
    <bean id="myInterfaceImpl" class="thispkg.MyInterfaceImpl"/>
    <aop:config proxy-target-class="true">
        <aop:aspect id="usageTrackerAspect" ref="mylogger">
            <aop:declare-parents types-matching="thispkg.RandomClass+" implement-interface="thispkg.MyInterface" default-impl="thispkg.MyInterfaceImpl"/>
            <aop:pointcut expression="this(thispkg.MyInterface)" id="randompointcut"/>
            <aop:before pointcut-ref="randompointcut" method="info"/>
        </aop:aspect>
    </aop:config>
</beans>

I have tried both thispkg.MyInterfaceImpl & thispkg.RandomClass in pointcut expression but still can't get the ========Info======== printed. Only prints

MyInterfaceImpl :: Hello world

Any clue ?


Answer:

I'm not sure if this is a bug or intended behavior.

You're adding MyInterface (and MyInterfaceImpl) as introductions with

<aop:declare-parents ... />

These are implemented with a specific interceptor (call it introduction interceptor) in the proxy object. The aspect is added as a separate interceptor (call it AOP interceptor) in the proxy. One cannot (does not) intercept the other.

If you do the following

RandomClass bean = context.getBean(RandomClass.class);
bean.suvichar();

your advice will get invoked because the AOP interceptor comes into play.

With

MyInterface in = (MyInterface) context.getBean("randomClass", RandomClass.class);
in.speak();

however, it's the introduction interceptor which handles the speak invocation. Your AOP interceptor is not involved and therefore doesn't invoke the before advice.