0

I've gone through many Aspect related posts, but none of them seem to help me. I see a lot of the posts are really old, and all the example GitHub repositories only feature a single .jar when I'm working with multiple.

I know my common jar is being included properly because I can see other code clearly working. When I build the common jar then I see my aspect printed in the output logs.

mvn clean install logs

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.8.13 built on Wednesday Nov 15, 2017 at 19:26:44 GMT
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info using configuration /C:/Users/<username>/Documents/IntelliJ/Team-Common/team-common/target/classes/META-INF/aop.xml
[AppClassLoader@18b4aac2] info using configuration file:/C:/Users/<username>/.m2/repository/org/springframework/spring-aspects/4.3.13.RELEASE/spring-aspects-4.3.13.RELEASE.jar!/META-INF/aop.xml
[AppClassLoader@18b4aac2] info register aspect com.mycompany.myteam.common.aspect.MyAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.transaction.aspectj.JtaAnnotationTransactionAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.cache.aspectj.AnnotationCacheAspect
[AppClassLoader@18b4aac2] info register aspect org.springframework.cache.aspectj.JCacheCacheAspect
[AppClassLoader@18b4aac2] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'org.springframework.cache.jcache.interceptor.JCacheAspectSupport' which cannot be found on the classpath
[AppClassLoader@18b4aac2] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'javax.cache.annotation.CacheResult' which cannot be found on the classpath
[IsolatedClassLoader@48503868] info AspectJ Weaver Version 1.8.13 built on Wednesday Nov 15, 2017 at 19:26:44 GMT
[IsolatedClassLoader@48503868] info register classloader org.apache.maven.surefire.booter.IsolatedClassLoader@48503868
[IsolatedClassLoader@48503868] info using configuration /C:/Users/<username>/Documents/IntelliJ/Team-Common/team-common/target/classes/META-INF/aop.xml
[IsolatedClassLoader@48503868] info using configuration file:/C:/Users/<username>/.m2/repository/org/springframework/spring-aspects/4.3.13.RELEASE/spring-aspects-4.3.13.RELEASE.jar!/META-INF/aop.xml
[IsolatedClassLoader@48503868] info register aspect com.mycompany.myteam.common.aspect.MyAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.transaction.aspectj.JtaAnnotationTransactionAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.cache.aspectj.AnnotationCacheAspect
[IsolatedClassLoader@48503868] info register aspect org.springframework.cache.aspectj.JCacheCacheAspect
[IsolatedClassLoader@48503868] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'org.springframework.cache.jcache.interceptor.JCacheAspectSupport' which cannot be found on the classpath
[IsolatedClassLoader@48503868] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'javax.cache.annotation.CacheResult' which cannot be found on the classpath

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

When I invoke the API in the UserSearch.jar it returns data properly, but the Aspect is never fired even though the controller method matches the pointcut of my aspect inside the Common Jar.

Why isn't my Common Jar aspect intercepting the UserSeach application?

Here is my application structure.

Common Jar

package com.mycompany.myteam.common.aspect;

@Aspect
@Component
public class MyAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(AuditAdvice.class);


    @Around("execution(public * com.mycompany.myteam.*.*Controller.*(..)) "
          + "&& !execution(public * com.mycompany.myteam.*.AuditController.*(..))")
    public Object aroundRestEndpoints(ProceedingJoinPoint pjp) throws Throwable {

        System.err.println("\n\n---------------------------------INSIDE ASPECT---------------------------------\n\n");

        return pjp.proceed();

    }
}
package com.mycompany.myteam.common.config;

@Configuration
@EnableAspectJAutoProxy
public class CommonAppConfig {

    // ... Unrelated 
}

/src/main/resources/META-INF/aop.xml

<aspectj>
    <aspects>
        <aspect name="com.mycompany.myteam.common.aspect.MyAspect"/>
        <weaver options="-verbose -showWeaveInfo">
            <include within="com.mycompany.myteam.*"/>
        </weaver>
    </aspects>
</aspectj>

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>com.mycompany.myteam.common</groupId>
    <artifactId>team-common</artifactId>
    <version>1.0.0</version>
    <name>team-common</name>
    <description>team-common</description>


    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <packaging>jar</packaging>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- Dependency Versions -->
        <aspectj.version>1.8.13</aspectj.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <dependencies>

        <!-- AOP -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>


        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>


    <repositories>
        <repository>
            <id>central</id>
            <name>libs-release</name>
            <url>http://somerepo.com/artifacts/release</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>snapshots</id>
            <name>libs-snapshot</name>
            <url>http://somerepo.com/artifacts/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>spring-milestones</name>
            <url>http://somerepo.com/artifacts/milestones</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.11</version>
                    <configuration>
                        <showWeaveInfo>true</showWeaveInfo>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <Xlint>ignore</Xlint>
                        <complianceLevel>${java.version}</complianceLevel>
                        <encoding>UTF-8</encoding>
                        <verbose>true</verbose>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>process-sources</phase>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.aspectj</groupId>
                            <artifactId>aspectjtools</artifactId>
                            <version>${aspectj.version}</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <argLine>-XX:-UseSplitVerifier</argLine>
                    <argLine>
                        -javaagent:"${settings.localRepository}"/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
                    </argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

UserSearch.jar

package com.mycompany.myteam.usersearch.controller;

@RestController
@RequestMapping("/usersearch")
public class UserSearchController {

    @Autowired
    private UserSearchService userSearchService;


    @RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
    public List<UserDTO> search(@PathVariable("name") String name){
        return userSearchService.search(name);
    }
}
package com.mycompany.myteam.usersearch;

@SpringBootApplication
@ComponentScan("com.mycompany.myteam")
public class UserSearchApplication {

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

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>com.mycompany.myteam.usersearch</groupId>
    <artifactId>user-search</artifactId>
    <version>1.0.0</version>
    <name>user-search</name>
    <description>user-search</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <packaging>jar</packaging>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.mycompany.myteam.usersearch.UserSearchApplication</start-class>
    </properties>

    <dependencies>

        <!-- Commons -->
        <dependency>
            <groupId>com.mycompany.myteam.common</groupId>
            <artifactId>team-common</artifactId>
            <version>1.0.0</version>
        </dependency>]

        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
kriegaex
  • 63,017
  • 15
  • 111
  • 202
wheeleruniverse
  • 1,511
  • 2
  • 20
  • 37
  • Your project settings are kind of paradoxical: On the one hand you configure Spring to use Spring AOP via `@EnableAspectJAutoProxy` and making your aspect a `@Component`, both of which is not necessary if you want to use AspectJ LTW. Then you configure Surefire to start your tests with an active load-time weaver. Last, but not least you also configure AspectJ Maven plugin for compile-time weaving (CTW), which is also unnecessary for LTW. So which of the three should it be: Spring AOP or AspectJ LTW or AspectJ CTW? Mixing all three is not helpful, it does not work like "high dosage helps much". – kriegaex Oct 08 '19 at 06:26
  • Sorry, I read a bunch of articles and examples and tried out a bunch. I think I need LTW because my '@Aspect' is in a different jar then the methods I want to advise. Is it enough to simply remove the components for CTW and Spring AOP? I want to leave the changes to UserSearch jar to a minimum because this Common Jar is supposed to be easy to include. – wheeleruniverse Oct 08 '19 at 10:58
  • You may think your pointcut matches, but actually `execution(public * com.mycompany.myteam.*.*Controller.*(..))` only matches `*Controller` methods in direct sub-packages of `com.mycompany.myteam`, e.g. `com.mycompany.myteam.usersearch`. Your `UserSearchController` is one level further down in `com.mycompany.myteam.usersearch.controller`, though. I recommend to use the `..` syntax in order to cover subpackages: `execution(public * com.mycompany.myteam..*Controller.*(..))`. Now it should match. The same applies to the second part of the pointcut. – kriegaex Oct 08 '19 at 11:53
  • Whether your aspect resides in the same or another package is completely irrelevant as long as your target classes are Spring beans/components. If they are, they can be intercepted by Spring AOP aspects. Otherwise they cannot. So you do not need AspectJ LTW or CTW in my opinion. If any of my remarks help you solve this, let me know, then I can convert my comments into an answer you can accept. Otherwise maybe later at home I have time to copy all your code into a project and run it. – kriegaex Oct 08 '19 at 11:55

1 Answers1

1

I copied your source and XML files into new Maven projects. What I wrote in my comments as an educated guess is actually true:

  • You do not need any AspectJ LTW or CTW, i.e. you can remove

    • aop.xml (and the META-INF folder),
    • AspectJ Maven plugin,
    • dependencies on AspectJ runtime and weaver,
    • Maven Surefire LTW configuration (remove the whole plugin).
  • Spring AOP works nicely with your multi-module setup.

  • As I said, please just fix your pointcut to match sub-packages:
@Around(
  "execution(public * com.mycompany.myteam..*Controller.*(..)) && " +
  "!execution(public * com.mycompany.myteam..AuditController.*(..))"
)

I had to fix some stuff in your classes (e.g. rename the aspect to match the logger name, add a dummy service and DTO with corresponding methods in order to make the code compile) and add H2 database driver to your user-search POM. Then everything worked nicely.

kriegaex
  • 63,017
  • 15
  • 111
  • 202