Top of the morning/noon/evening!
I have a multi project setup in which I use an annotation processor. This annotation processor is supposed to pickup Plugin instances (a custom interface) during the compilation, which are loaded using the ServiceLoader. The goal is to distribute the annotation processor to applications using the maven-compiler-plugin. However, maven is not picking up plugins Plugin instances from other dependencies.
To illustrate the setup and show the issue, I will use 3 projects:
Project A: Contains an Annotation Processor. This processor tries to load additional classes called Plugin on compile-time using the Java standard ServiceLoader, like this:
ServiceLoader.load(type)
.stream()
.map(provider -> injector.get(provider.type()))
.peek(it -> {
it.initialize();
logger.debug(() -> "Initialized ProcessorPlugin: " + it.getClass().getSimpleName());
})
.toList();
This project is bundled into a jar file and used by Project C.
Project B: This project contains a Plugin implementation. The goal is that this is picked up by the annotation-processor of Project A during the compilation of Project C. The compiled jar of Project B contains the Plugin implementation and the META-INF/services file to expose this plugin to the ServiceLoader.
Project C: This is the "final application". In here we include the annotation processor using the maven-compiler-plugin, like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<parameters>true</parameters>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>my.group-id</groupId>
<artifactId>processor</artifactId>
<version>${processor.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</plugin>
As the annotation processor should later be distributed using a pre-configured parent pom, this approach should (if possible) not change.
My initial assumption was, that if I include the dependency like this, it should be visible to the processor:
<dependency>
<groupId>my.group-id</groupId>
<artifactId>plugin</artifactId>
</dependency>
However, this does not work; the processor of Project A is not picking up the plugin of Project B when I run mvn clean compile in Project C. If I run a manual compilation test (using the JavaCompiler class to manually compile classes in a junit test and adding the annotation processor), the plugin is picked up and processed correctly.
The same is also true, if I add the dependency directly to the maven-compiler-plugin, like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<parameters>true</parameters>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>my.group-id</groupId>
<artifactId>processor</artifactId>
<version>${processor.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>my.group-id</groupId>
<artifactId>plugin</artifactId>
<version>...</version>
</dependency>
</dependencies>
</plugin>
This approach would be less favorable, but if it would have worked, it would have been a first step. However, this also does not work.
One thing I know that does work, is to not include it using the maven-compiler-plugin. If the annotation-processor is included as a provided dependency like this:
<dependency>
<groupId>my.group-id</groupId>
<artifactId>processor</artifactId>
<scope>provided</scope>
</dependency>
the annotation processor picks up the plugins correctly and works as expected. But now I have the issue, that I cannot create a simple parent for developers to use. Instead each project that wants to use this, needs to specify the processor like this. If push comes to shove, this solution will do, but I want to know if it is possible to achieve this using the compiler plugin.
I have searched the internet for answers, but not found any solutions to make this work using the maven-compiler-plugin. I also did not find anything in the documentation of the maven-compiler-plugin.
Do I need to configure the maven-compiler-plugin in a special way to let it pick up the plugin of Project B correctly? Is there another plugin that can make this work that I have missed? Or is this simply not possible?
Thank you very much in advance!
edit 1: This is the general project setup I want to achieve.
The Project C uses a parent, which looks something like this:
<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>my.group-id</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<parameters>true</parameters>
<annotationProcessorPaths>
<annotationProcessorPath>
<groupId>my.group-id</groupId>
<artifactId>processor</artifactId>
<version>${processor.version}</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And the project itself looks something like this:
<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>
<artifactId>project-c</artifactId>
<version>${revision}</version>
<parent>
<groupId>my.group-id</groupId>
<artifactId>parent</artifactId>
<version>${parent.version}</version>
</parent>
<dependencies>
<dependency>
<!-- This is the plugin that the annotation processor should pick up -->
<groupId>my.group-id</groupId>
<artifactId>plugin</artifactId>
<version>${plugin.version}</version>
<scope>provided</scope> <!-- Scope does not matter for this example -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
As you can see, the parent sets up the annotation processor to be included in the maven-compiler-plugin. Project C uses the compiler-plugin. This in itself works, the annotation processor is running successfully, but the plugin dependency is not picked up.
If I change it, so that the annotation processor is not included in the compiler-plugin, but as a provided dependency like this:
<?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>
<artifactId>project-c</artifactId>
<version>${revision}</version>
<dependencies>
<dependency>
<!-- This is the plugin that the annotation processor should pick up -->
<groupId>my.group-id</groupId>
<artifactId>plugin</artifactId>
<version>${plugin.version}</version>
<scope>provided</scope> <!-- Scope does not matter for this example -->
</dependency>
<dependency>
<groupId>my.group-id</groupId>
<artifactId>processor</artifactId>
<version>${processor.version}</version>
<optional>true</optional>
<scope>provided</scope><!-- Scope does not matter for this example -->
</dependency>
</dependencies>
</project>
the compiler plugin correctly picks up the annotation processor and the plugin is loaded correctly. However, if possible I want to have the processor in the maven-compiler-plugin and still pickup the plugin.
<pluginManagement>? I think you can configure that in a parent. Can you share a full (minimal) example of such a POM that would work but doesn't work with the parent?mvn help:effective-pomor similar to see the child POM with everything from the parent added.pluginartifact toannotationProcessorPathssection as well.