Open snicoll opened 1 month ago
Our usecase, as described in https://github.com/spring-projects/spring-boot/issues/32853 is that we have the devtools on the runtime classpath. Native image automatically includes the whole runtime classpath in the native image (at least what's reachable).
On Spring Boot startup, the spring.factories
contained in the devtools instructs the Spring Framework to enable devtools. However, devtools in a native image don't make much sense - these tools are for development only.
We worked around that by adding an if
in the devtools startup and let it disable itself if it's running in a native image - however, the code is still contained in the native image.
To fix that problem at the root, it would be nice to do something like this:
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<excludeDependency> <!-- Or maybe just name the tag 'exclude'? -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</excludeDependency>
</configuration>
</plugin>
</plugins>
</build>
and the native-maven-plugin
would not include any classes from that jar in the native image.
Another option would be, like Stephane suggested, to add a key to the manifest (e.g. Native-Image-Exclude: true
) and the native image build tools then exclude that from the classpath.
This approach would be more flexible, as this doesn't need a hard-coded list of dependencies.
We hit similar issues I believe. Just out of interest.. does using provided
scope not work?
The devtools should be on the classpath when developing the application on the JVM but not when building the native image. Usually, this is in the pom.xml with devtools:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
The devtools should be on the classpath when developing the application on the JVM but not when building the native image
You can achieve that with provided
scope.
It should be on the runtime classpath when developing the application (it does stuff when you run the application on the JVM, like reloading classes), but it should not be on the classpath when compiling the native image. I don't think this is possible with the provided
scope?
provided
: This is much likecompile
, but indicates you expect the JDK or a container to provide the dependency at runtime.
Who would provide this dependency?
So provided
is close to compileOnly
in Gradle. Those dependencies are in the compilation classpath, but certainly not at runtime.
That said, if you have control over the classpath of the app running in dev mode, you could choose to include dependencies in provided
scope. This is what we do in the Micronaut Maven Plugin, so effectively, provided
becomes a sort of "development only" scope.
And this will also have the desired effect of not including such dependencies in the native image.
if you have control over the classpath of the app running in dev mode
While this could be made to work with mvn spring-boot:run
, I don't think this will be possible when running the application from the IDE, which a lot of users do. Or did you get this working in Micronaut?
Yes, in Intellij IDEA at least, provided
dependencies are included in the runtime classpath.
Is your feature request related to a problem? Please describe. Maven has a limited list of dependency scopes and it's not possible to create custom ones. As such, dependencies that are development only can end up on the classpath. This has caused issues in the past for things that need to build an executable based on a Maven project.
Spring Boot has had several issues such as https://github.com/spring-projects/spring-boot/issues/13289 and implemented several features to allow dependencies to be excluded:
The Maven plugin for native build tools urrently works in two modes: it builds the classpath itself, or it lets you define it. It would be nice if we could configure it to be able to exclude certain dependencies that shouldn't be analyzed by native-image in the first place.
Describe the solution you'd like A way to exclude a dependency. Either by providing the GAV in the plugin configuration or via a manifest entry. The latter looks less invasive and would work out of the box.
Describe alternatives you've considered None as building the classpath ourselves isn't really practical with Maven. The plugin is configured in our maven parent and used in a wide range of contexts.