Why AspectJ doesn't catch event?

67 Views Asked by At

I'm trying to launch a simple example of AspectJ code inside the Gradle project.

build.gradle:

plugins {
  id 'java'
  id "io.freefair.aspectj" version "5.1.1"
}

group = 'org.example'
version = '1.0-SNAPSHOT'

repositories {
  mavenCentral()
}

sourceSets {
  main {
    java {
      srcDirs = ['src/main/java', 'src/main/aspectj']
    }
  }

  test {
    java {
      srcDirs = ['src/test/java']
    }
  }
}

dependencies {
  testImplementation platform('org.junit:junit-bom:5.9.1')
  testImplementation 'org.junit.jupiter:junit-jupiter'
  testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.23.1'
  testImplementation group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.6'
  implementation group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.6'
  implementation group: 'org.aspectj', name: 'aspectjrt', version: '1.9.6'
  testImplementation group: 'org.aspectj', name: 'aspectjrt', version: '1.9.6'
  testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2'
  testImplementation 'junit:junit:4.13.1'
}

test {
  useJUnitPlatform()
}

In the folder 'src/main/aspectj' class org.example.aspectj.DemoAspect

package org.example.aspectj;

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

@Aspect
public class DemoAspect {
  @Before("execution(* *(..)) && !within(org.example.aspectj.DemoAspect)")
  public void logEnter(JoinPoint joinPoint) {
    System.out.println("!!!!!!DemoAspect");
    System.out.print(joinPoint.getStaticPart());
    System.out.print(" -> ");
    System.out.println(joinPoint.getSignature());
  }
}

In the folder 'src/main/java' class org.example.aspectj.Main

package org.example.aspectj;

import java.util.Date;

public class Main {
  public static void main(String[] args) {
    System.out.println("new Date() -> " + new Date());
  }
}

I'm running Main class. Code from DemoAspect was not called. What is wrong in configuration?

1

There are 1 best solutions below

3
kriegaex On

I tried with the old plugin version 5.1.1 you are using and Gradle 6.6.1. If the aspect is in src/main/aspectj and the application class in src/main/java, the AspectJ compiler (Ajc) says:

[warning] advice defined in org.example.aspectj.DemoAspect has not been applied [Xlint:adviceDidNotMatch]

Moving everything to src/main/aspectj makes it work.

I suggest upgrading to the latest Freefair plugin version 8.6. It now does not need src/main/aspectj anymore (even though it still recognises it and you can put your aspects there), but you can put everything into src/main/java, which is more convenient and also in line with how AspectJ Maven Plugin does it. You may also want to upgrade to AspectJ 1.9.21.2, which still supports older compilation targets like Java 8, but also up to Java 21. Just make sure to run the build on JDK 17+. Your program can then run on an older JRE, depending on targetCompatibility.

plugins {
  id 'java'
  id 'io.freefair.aspectj' version '8.6'
}

group = 'org.example'
version = '1.0-SNAPSHOT'

repositories {
  mavenCentral()
}

java {
  sourceCompatibility = '8'
  targetCompatibility = '8'
}

dependencies {
  implementation group: 'org.aspectj', name: 'aspectjrt', version: '1.9.21.2'
}

test {
  useJUnitPlatform()
}

Please note that you only need a dependency on aspectjrt in your project. The plugin will figure out which compiler version to use on its own.

package org.example.aspectj;

import java.util.Date;

public class Main {
  public static void main(String[] args) {
    System.out.println("new Date() -> " + new Date());
  }
}

I also simplified your log output a bit, simply logging the join point instead of making method calls on it.

package org.example.aspectj;

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

@Aspect
public class DemoAspect {
  @Before("execution(* *(..)) && !within(org.example.aspectj.DemoAspect)")
  public void logEnter(JoinPoint joinPoint) {
    System.out.println(joinPoint);
  }
}

Running the build on Gradle 8.4 and JDK 17 or 21 and then the main class yields:

Starting Gradle Daemon...
Gradle Daemon started in 2 s 154 ms
> Task :compileJava SKIPPED
> Task :compileAspectj
> Task :processResources NO-SOURCE
> Task :classes

> Task :Main.main()
execution(void org.example.aspectj.Main.main(String[]))
new Date() -> Sun Mar 17 09:16:09 CET 2024