I have put the MCVE code for this on GitHub - https://github.com/ravitechy/multi-module-project/tree/main.
Update by @kriegaex 2024-12-20: Because the OP @Ravi deleted the original repository and with it also my PR, please just clone my fork. The PR was the same as these commits.
I have two modules in my Java project (built on Gradle) - app
which depends on commons
.
commons
contain the Aspect class BasicCommonAspect
as defined below
package org.example.commons.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import javax.annotation.PostConstruct;
@Aspect
@EnableAspectJAutoProxy
public class BasicCommonAspect {
@Before("@annotation(bca) && execution(* *(..))")
public void executeBeforeForCommonAnnotation(JoinPoint joinPoint, BasicCommonAnnotation bca) {
System.out.println("BasicCommonAnnotation detected");
}
}
commons
also contain an annotation BasicCommonAnnotation
like this
package org.example.commons.aspect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BasicCommonAnnotation {
}
app
contains AppBackground
and has a method run
annotated with BasicCommonAnnotation
package org.example;
import org.example.commons.aspect.BasicCommonAnnotation;
public class AppBackground {
@BasicCommonAnnotation
public void run() {
System.out.println("Running in background");
}
}
There is a driver class in app
module named RunApp
which invokes the run
method in AppBackground
package org.example;
public class RunApp {
public static void main(String[] args) {
final AppBackground background = new AppBackground();
background.run();
}
}
I am using post-compile weaving (using the Gradle plugin io.freefair.aspectj.post-compile-weaving
) since I need to use Project Lombok.
When I run the RunApp
class, my aim is to see the method BasicCommonAspect.executeBeforeForCommonAnnotation()
executed as per the advice defined.
From my preliminary research, I got to know that I need to include the external module as an aspect library in apps
module. I found a Stack Overflow answer for the exact same problem here - AspectJ - Aspect from external JAR, but it was for the Maven build. I am looking for exactly similar configuration for my Gradle project.
I tried using inpath
as suggested here https://github.com/freefair/gradle-plugins/issues/450, but I began running into different build errors now as indicated below.
Not skipping AJC (inpath is set)
Starting process 'command 'D:\OpenJdk17\bin\java.exe''. Working directory: D:\intellij-idea workspace\multi-module-project\app Command: D:\OpenJdk17\bin\java.exe -Dfile.encoding=windows-1252 -Duser.country=IN -Duser.language=en -Duser.variant -cp C:\Users\raviteja.kothapalli\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjtools\1.9.8\caf8b7f9023d93af2ed2e6e8bf023a800e9d1323\aspectjtools-1.9.8.jar org.aspectj.tools.ajc.Main -argfile D:\intellij-idea workspace\multi-module-project\app\build\tmp\compileJava\ajc.options
Successfully started process 'command 'D:\OpenJdk17\bin\java.exe''
←[0K
←[0K
←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [18s]←[m←[35D←[1B←[1m> :app:compileJava←[m←[18D←[1B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [19s]←[m←[35D←[2B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [20s]←[m←[35D←[2B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [21s]←[m←[35D←[2B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [22s]←[m←[35D←[2B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [23s]←[m←[35D←[2B←[2AC:\Users\raviteja.kothapalli\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\2.7.18\9cf147c6ca274c75b32556acdcba5a1de081ebcd\spring-boot-autoconfigure-2.7.18.jar [error] can't determine implemented interfaces of missing type org.springframework.web.server.WebExceptionHandler
when weaving type org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler
when weaving classes
when weaving
when batch building BuildConfig[null] #Files=0 AopXmls=#0
[Xlint:cantFindType]
(no source information available)
[Xlint:cantFindType]
←[0K
←[0K
←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [23s]←[m←[35D←[1B←[1m> :app:compileJava←[m←[18D←[1B←[2A←[1m<←[0;32;1m===←[0;39;1m----------> 25% EXECUTING [24s]←[m←[35D←[2B←[2AC:\Users\raviteja.kothapalli\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\2.7.18\f6dbdd8da7c2bded63dff9b1f48d01a4923f20a0\spring-boot-2.7.18.jar [error] can't determine implemented interfaces of missing type javax.servlet.Filter
when weaving type org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter
when weaving classes
when weaving
when batch building BuildConfig[null] #Files=0 AopXmls=#0
[Xlint:cantFindType]
(no source information available)
[Xlint:cantFindType]
C:\Users\raviteja.kothapalli\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\2.7.18\f6dbdd8da7c2bded63dff9b1f48d01a4923f20a0\spring-boot-2.7.18.jar [error] can't determine implemented interfaces of missing type io.undertow.server.HttpHandler
when weaving type org.springframework.boot.web.embedded.undertow.UndertowWebServer$CloseableHttpHandlerFactory$1
when weaving classes
when weaving
when batch building BuildConfig[null] #Files=0 AopXmls=#0
[Xlint:cantFindType]
(no source information available)
[Xlint:cantFindType]
C:\Users\raviteja.kothapalli\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\2.7.18\f6dbdd8da7c2bded63dff9b1f48d01a4923f20a0\spring-boot-2.7.18.jar [error] can't determine implemented interfaces of missing type org.springframework.web.server.WebFilter
when weaving type org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter
when weaving classes
when weaving
when batch building BuildConfig[null] #Files=0 AopXmls=#0
[Xlint:cantFindType]
(no source information available)
[Xlint:cantFindType]
So, what I understood is that I need to include the aspect classes only from specific packages in the inpath
in order to overcome the issue, but I can't seem to find the configuration to do it.
Please help me in providing the necessary configuration to include the aspects from external JARs/modules only from specific packages.
build.gradle
file in apps
module
plugins {
id 'java'
id 'java-library'
id 'io.freefair.aspectj.post-compile-weaving' version "${aspectjVersion}"
}
java.sourceCompatibility = JavaVersion.VERSION_17
java.targetCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
// api project(":commons")
inpath project(":commons")
api libs.spring.boot.starter
annotationProcessor libs.lombok
implementation libs.aspectjrt
}
build.gradle
in commons
module
plugins {
id 'java'
id 'java-library'
id 'io.freefair.aspectj.post-compile-weaving' version "${aspectjVersion}"
}
java.sourceCompatibility = JavaVersion.VERSION_17
java.targetCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
api libs.spring.boot.starter
annotationProcessor libs.lombok
implementation libs.aspectjrt
}
settings.gradle
in root
rootProject.name = 'multi-module-project'
include('app')
include('commons')
dependencyResolutionManagement {
versionCatalogs {
libs {
version('spring-boot-ver', '2.7.18')
library('lombok', 'org.projectlombok:lombok:1.18.30')
library('spring-boot-starter', 'org.springframework.boot', 'spring-boot-starter').versionRef('spring-boot-ver')
library('aspectjrt','org.aspectj:aspectjrt:1.9.8')
}
testLibs {
library('junit-jupiter-api','org.junit.jupiter:junit-jupiter-api:5.8.1')
library('junit-jupiter-engine', 'org.junit.jupiter:junit-jupiter-engine:5.8.1')
}
}
}
build.gradle
in root
rootProject.ext {
projectGroup = 'org.example'
projectVersion = '1.0.0-SNAPSHOT'
aspectjVersion = '8.4'
}
P.S: Everything is working as expected if all the classes, annotations and aspects are in one single module.
The problem is inpath project(":commons")
in your application module. The inpath is meant to be used, if you want to weave aspects into a third-party module. The latter would go on the inpath. But in this case, you simply want to tell the plugin where to find aspects to weave into the current module. The aspect library, however, belongs on the aspectpath.Therefore, you need to change the line to aspect project(":commons")
. This is the equivalent to <aspectLibrary/>
from my answer to the corresponding Maven question you already found
I have created a pull request for your project, fixing this problem and improving a few other things. Just go through the commit diffs and comments one by one.
Now, you can build and run your application. The console log says:
> Task :app:RunApp.main()
BasicCommonAnnotation detected
Running in background
I.e., the aspect gets triggered as expected.
Update 2024-12-20: Because the OP @Ravi deleted the original repository and with it also my PR, please just clone my fork. The PR was the same as these commits.