Open wilkinsona opened 2 years ago
Based on my test with Spring Boot 3.0.1, the behavior I see is that creating a project on https://start.spring.io/ with native and Devtools works with Gradle but is broken with Maven at runtime with this exception: https://gist.github.com/sdeleuze/4b3eda4fedfb98eef820cc8888af9c26
Maybe fixing this issue would fix that error and remove the bloat at the same time?
I have encountered the same issue with maven when using spring-boot:build-image the native image will work, but when using native:compile running the executable will fail due to devtools even though it was configured as an optional dependency. Removing devtools as dependecy from the pom.xml resolves the problem.
We can exclude the devtools in org.springframework.boot.maven.ProcessAotMojo#getClassPath
with this:
Exclude exclude = new Exclude();
exclude.setGroupId("org.springframework.boot");
exclude.setArtifactId("spring-boot-devtools");
return getClassPath(directories, new ExcludeTestScopeArtifactFilter(), new ExcludeFilter(exclude));
But this only excludes the devtools from the AOT processing phase, not from the inclusion in the native image and it will still fail when the native binary runs.
We don't supply native-image with the classpath, this is done in the native-maven-plugin
itself here: https://github.com/graalvm/native-build-tools/blob/c4762a78f9c80b653ff4e3be8f3bb3fc6dd60d90/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeImageMojo.java#L323
One can override the whole classpath used for native compilation. We don't do that in our starter-parent, we only point native-image to our classes (application classes and AOT generated classes) and let native image itself figure out the classpath.
I think the way forward would be to add something to native-maven-plugin
which enables automatic population of the classpath (which is already implemented) but with the option of excluding dependencies. We could then add the exclusion of the devtools in our starter-parent.
What do you think?
That sounds like a good long-term solution although I wonder if they'd agree to the extra complexity for something that is probably quite unusual. In the shorter term, I think we should consider updating DevToolsEnablementDeducer
to disable DevTools in a native image. This will still be useful in the longer term even with the proposed changes to the native Maven plugin if the dependency ends up in the native image anyway, for example because someone isn't using spring-boot-starter-parent
.
Projects with devtools included are now working again with Maven. The DevToolsPropertyDefaultsPostProcessor
will now back off in a native image. The code is still included in the native image, but it won't run.
The problem with excluding devtools from the classpath when building a native image still stands.
+1. Also experiencing this issue.
@oliveryasuna what problem are you experiencing? AFAIK, there are no longer any problems with Devtools in a native image as it will be disabled.
Could be https://github.com/spring-projects/spring-boot/issues/35853, this currently breaks Petlinic with Maven when org.springframework.boot:spring-boot-devtools
is added.
Thanks, @sdeleuze. I'd forgotten about that one. @oliveryasuna, are you using Spring Boot 3.1.0?
Hi @wilkinsona, I am experiencing the same issue using Spring Boot 3.1.0. When spring-boot-devtools are included in pom.xml, the application throws the following exception at startup:
at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$throwing$0(SpringFactoriesLoader.java:651)
at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$handleMessage$3(SpringFactoriesLoader.java:675)
at org.springframework.core.io.support.SpringFactoriesLoader.instantiateFactory(SpringFactoriesLoader.java:231)
at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:206)
at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:160)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:462)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:458)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:274)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:253)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294)
at si.um.feri.isl.dataHub.DataHub.main(DataHub.java:26)
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.devtools.restart.RestartScopeInitializer
at java.base@17.0.5/java.lang.Class.forName(DynamicHub.java:1132)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
at org.springframework.core.io.support.SpringFactoriesLoader.instantiateFactory(SpringFactoriesLoader.java:224)
... 9 more```
However, when I remove spring-boot-devtools dependency everything works fine.
My workaround was to make spring-boot-devtools
scope provided
in my native
profile.
Thanks, both. This should bee fixed in tomorrow's 3.1.1 release through #35853.
@wilkinsona Yes, I am using 3.1.0. AOT includes Devtools.
To hopefully get the ball rolling again, I've submitted a RFE for the native image Maven plugin, see https://github.com/graalvm/native-build-tools/issues/612
We've had a couple of issues in this area already:
The first was Maven-specific as, when using Gradle, the
developmentOnly
configuration meant that DevTools wasn't on the classpath when performing AOT processing with Gradle. It was fixed by disabling DevTools during AOT processing. The second was Gradle-specific asdevelopmentOnly
dependencies were only the classpath of the native image but they hadn't been processed ahead-of-time so a failure occurred when the native image was started.With the first fix in place, a Maven-built native image will include DevTools but it'll be disabled. As such, its inclusion is benign other than bloating the image. That bloat is only ~145KB as far as I can tell, but we should eliminate it if we can by removing DevTools from the classpath.