Search code examples
javamavenaspectj

Aspect not being compile-time woven into target classes despite seemingly correct configuration


I have been successfully using Aspects with CTW for some time, although always for weaving code I link against, rather than code I compile.

In a test project, reusing the configurations that allowed me to make CTW work for external classes, I've been trying to weave code I compile, but had no success.

I'd be grateful to anyone who could help me spot whatever it is that I'm doing wrong here.

I tried both the call and the execution approach, but to no avail.

The intended behavior is to intercept all method calls within the com.budwhite.studying.aspect.logging.service package, print a log message before their execution, and another log message after their execution.

I tried adding the aspectj-report goal to the aspectj-maven-plugin execution, and the generated documents do say that my LoggingAspect is advising the classes within that package - but in practice the aspect logic isn't executed when those methods are invoked - and I can't see any trace of the woven aspect code within the .class files.

All the configuration can be found in the GH repo I linked, but here are the main bits from the execution attempt (which is the approach I am successfully using in other projects, weaving code I link against):

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.budwhite.studying</groupId>
    <artifactId>aspect-logging</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <logback.version>1.3.11</logback.version>
        <aspectj.version>1.8.13</aspectj.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <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>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>${maven.compiler.source}</complianceLevel>
                    <encoding>UTF-8</encoding>
                    <verbose>true</verbose>
                    <sources>
                        <source>
                            <basedir>src/main/java</basedir>
                            <includes>
                                <include>**/LoggingAspect.java</include>
                            </includes>
                        </source>
                    </sources>
                </configuration>
                <executions>
                    <execution>
                        <!-- IMPORTANT -->
                        <phase>process-sources</phase>
                        <goals>
                            <goal>aspectj-report</goal>
                            <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>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <argLine>-XX:-UseSplitVerifier</argLine>
                    <argLine>
                        -javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
                    </argLine>
                    <useSystemClassLoader>true</useSystemClassLoader>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

aop.xml

<aspectj>
    <weaver options="-verbose -showWeaveInfo">
        <include within="**.LoggingAspect"/>
        <include within="com.budwhite.studying.aspect.logging.service..*"/>
    </weaver>
    <aspects>
        <!-- Aspects -->
        <aspect name="**.LoggingAspect"/>
    </aspects>
</aspectj>

LoggingAspect.java

package com.budwhite.studying.aspect.logging.aspect;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.stream.Collectors;

import static java.lang.System.currentTimeMillis;

@Aspect
public class LoggingAspect {

    private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
    @Around("execution(* com.budwhite.studying.aspect.logging.service..*(..))")
    public Object whatever(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println("EVEN IF I DID SOMETHING WRONG WITH SLF4J, THIS PRINTOUT SHOULD SHOW UP");
        logger.warn("{} begins, args are [{}]",
                thisJoinPoint.getSignature().getName(),
                Arrays.stream(thisJoinPoint.getArgs())
                        .map(Object::toString)
                        .collect(Collectors.joining(",")));
        long startTime = currentTimeMillis();
        Object result = thisJoinPoint.proceed();
        logger.warn("{} ends, execution time {} ms, output is {}",
                thisJoinPoint.getSignature().getName(),
                currentTimeMillis()-startTime,
                result!=null ? result : ""
                );
        return result;
    }
}


Solution

  • Over-configuration is the cause of your problem. Simply remove the <sources/> section, which limits the AspectJ compiler to only compile the aspect but not the remaining code it ought to be woven into. If you do that, your sample project immediately works.

    Anyway, here is a somewhat more streamlined version of your POM, using the dev.aspectj plugin instead of the Mojohaus one (even though upgrading that one to 1.14.0 would also suffice for Java 8 or 11). As of today, the Mojohaus plugin still does not support Java 17+, while the AspectJ.dev one does.

    <?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.budwhite.studying</groupId>
      <artifactId>aspect-logging</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <logback.version>1.3.11</logback.version>
        <aspectj.version>1.9.20.1</aspectj.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>${logback.version}</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>${aspectj.version}</version>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
              <source>${maven.compiler.source}</source>
              <target>${maven.compiler.target}</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>dev.aspectj</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.13.1</version>
            <configuration>
              <complianceLevel>${maven.compiler.source}</complianceLevel>
              <showWeaveInfo>true</showWeaveInfo>
              <Xlint>ignore</Xlint>
              <encoding>UTF-8</encoding>
            </configuration>
            <executions>
              <execution>
                <goals>
                  <goal>aspectj-report</goal>
                  <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>
      </build>
    
    </project>
    

    Please also get rid of your aop.xml, because you are not using load-time weaving and also should not in your test, because with CTW that simply is not necessary.

    P.S.: Here is a pull request for you. Sorry for reformatting the files to indentation with 2 instead of 4 spaces. My IDE does that. You can simply activate this option when reviewing the diff:

    "Hide whitespace" option on GitHub