0

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.

15
  • What about using <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? Commented Jan 23, 2024 at 21:37
  • Yes, sure, i will update today after work. However, the short Form is, that I have a parent for Projekt C, that defines the compiler-plugin with the annotation processor preconfigured. This is what I want to achieve, but what does not work. Commented Jan 24, 2024 at 6:18
  • Please also show the configuration that doesn't work (both the parent and the child). Also, I think you can use mvn help:effective-pom or similar to see the child POM with everything from the parent added. Commented Jan 24, 2024 at 7:54
  • I have updated the question and added a minimal pom of Project C, as well as the parent that it is using. In general, the annotation processor is running, but it is failing to pickup the plugin using the ServiceLoader. I hope that it is clearer now :) Commented Jan 24, 2024 at 15:51
  • 1
    @ThorbenKuck add your plugin artifact to annotationProcessorPaths section as well. Commented Jan 24, 2024 at 18:46

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.