1

I have a maven project with modules. The parent for my root project is spring-boot-starter-parent, which provides a lot of dependency management.

In my module, I use spring-boot-configuration-processor, which is one of the dependencies managed by spring-boot-starter-parent (well, actually managed by its parent, spring-boot-dependencies).

If I don't specify the version in the plugins section, my build fails with:

Resolution of annotationProcessorPath dependencies failed: For artifact {org.springframework.boot:spring-boot-configuration-processor:null:jar}: The version cannot be empty. -> [Help 1]

So, I am forced to have the plugins section look like this:

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <annotationProcessorPaths>
                <path>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-configuration-processor</artifactId>
                    <version>2.6.0</version>
                </path>
            </annotationProcessorPaths>
        </configuration>
    </plugin>
</plugins>

However, I would prefer to reference the inherited version. Although spring-boot-dependencies has a lot of properties for the versions of various dependencies, it does not have a property for the version of spring-boot-configuration-processor. Nor does it include spring-boot-configuration-processor in plugin management.

How do I use the inherited version of this plugin instead of having to explicitly specify the version myself?

  • I don't think you can. Maven lets you inherit version for dependencies and plugins, but this is a special case because it's the *configuration* of a plugin. You can at least take advantage of the fact that the version of spring-boot-configuration-processor will match spring-boot-starter-parent, so you can declare your own property `spring.version` set to 2.6.0 and then use it for both of them. – Michael Dec 02 '21 at 23:40
  • @Michael I tried that, but it gave a different error: `Non-resolvable parent POM: Could not find artifact org.springframework.boot:spring-boot-starter-parent:pom:${spring.version} in central (https://repo.maven.apache.org/maven2) and 'parent.relativePath' points at no local POM` – Fractal Lotus Dec 03 '21 at 02:55

2 Answers2

0

You need to inherit from parent POM:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>{YOUR_VERSION}</version>
</parent>
Eslam Hamdy
  • 7,126
  • 27
  • 105
  • 165
0

I do believe instead of configuring maven-compiler-plugin you just need to declare spring-boot-configuration-processor as a dependency of your project with scope=provided - the purpose of annotationProcessorPaths and annotationProcessors parameters of maven-compiler-plugin is not to add annotation processor, but to force the compiler to use defined annotation processors only.

<plugins>
...
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
    </plugin>
...
</plugins>

<dependencies>
...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <scope>provided</scope>
    </dependency>
...
</dependencies>
Andrey B. Panfilov
  • 4,324
  • 2
  • 12
  • 18
  • I looked up "provided" scope, but I still don't really understand why that made it work. Why does it need to have this scope, and what is the thing that actually does the "providing" of the dependency in this case? – Fractal Lotus Dec 03 '21 at 03:12
  • 2
    in your case `scope=provided` causes maven compiler plugin to add dependency to the classpath when compiling, so javac will be able to discover annotation processors provided by such dependencies, but the resulting artifact will not depend on them. The another use case for `scope=provided` is to ban undesirable dependencies via dependencyManagement instead of putting tons of excludes – Andrey B. Panfilov Dec 03 '21 at 03:27
  • 1
    @FractalLotus It shouldn't need to be transitive in order to work. Provided scope basically just means that the dependency should not be transitive. If no projects are depending on your project then the scope is irrelevant. The name comes from the days of Jboss etc. where the application server would *provide* some dependencies, and you just declared them in your POM so you could compile against the API. Considering you're using Spring Boot, you're almost certainly not using an app server, so it's not helpful to think of it in those terms. – Michael Dec 03 '21 at 03:27
  • 1
    "causes maven compiler plugin to add dependency to the classpath when compiling" The implicit/default scope (compile) will also do this. The only thing that provided does additionally is prevent transitivity. – Michael Dec 03 '21 at 03:29
  • @Michael Can't agree with you: springboot-maven-plugin packs all compile dependencies into resulting jar which is actually not desired for particular dependency, `scope=provided` prevents it from doing that. – Andrey B. Panfilov Dec 03 '21 at 03:33
  • 1
    @AndreyB.Panfilov If you are going to attempt to correct me, make sure you are actually correct: https://github.com/spring-projects/spring-boot/issues/413 I've had exactly this issue in the past, where, to my surprise, Lombok jar was ending up in my final artifact despite being given provided scope. – Michael Dec 03 '21 at 11:42
  • Well, my bad - my point was based on common sense, best practices and structure of my projects (just on main class in maven module), never thought springboot guys may do weird things: "The reason for this is that many developers are used to adding things like servlet-api as provided. Since there won't be a servlet container to actually "provide" the dependency we package it inside the JAR" - they put tomcat-embed-core into jar which does contain servlet api, extracting controllers into separate module will also prevent plugin from packaging servlet-api, ridiculous behaviour. – Andrey B. Panfilov Dec 03 '21 at 12:17