Closed
Description
I noticed this when upgrading to Spring Boot 3.0.6 or 3.0.7, the build process works, but when I run the native image
it fails.
I'm using sdkman
installed GraalVM
with identifier 22.3.2.r17-grl
Steps to reproduce:
#Create a simple Spring Shell application with Spring Initializr using dependencies native,spring-shell
curl https://start.spring.io/starter.tgz -d dependencies=native,spring-shell -d javaVersion=17 -d bootVersion=3.0.7 -d type=maven-project | tar -xzf - || exit
Add a custom prompt component to the class:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@ShellComponent
class BugExample {
private final static File POM_FILE = new File("./pom.xml");
@ShellMethod("Hello")
@ShellMethodAvailability("pomFile")
public String hello(@ShellOption(defaultValue = "World") String version) {
return String.format("Hello, %s", version);
}
public Availability pomFile() {
return POM_FILE.exists() ? Availability.available()
: Availability.unavailable(String.format("%s does not exist", POM_FILE.getName()));
}
}
Optionally, replace the application.properties with application.yaml
logging:
level:
root: 'off'
spring:
main:
banner-mode: 'off'
web-application-type: 'NONE'
shell:
history:
enabled: 'false'
Build the native image:
./mvnw -Pnative clean native:compile -DskipTests
Run the image:
./target/demo help
With 3.0.5 I get the expected result
This is the result:
Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: Runtime reflection is not supported for public org.springframework.shell.Availability com.example.demo.BugExample.pomFile()
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89)
at java.base@17.0.7/java.lang.reflect.Method.acquireMethodAccessor(Method.java:76)
at java.base@17.0.7/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:281)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:265)
at org.springframework.shell.standard.StandardMethodTargetRegistrar.lambda$findAvailabilityIndicator$8(StandardMethodTargetRegistrar.java:331)
at org.springframework.shell.command.CommandRegistration$DefaultCommandRegistration.getAvailability(CommandRegistration.java:1237)
at org.springframework.shell.standard.commands.CommandInfoModel.of(CommandInfoModel.java:80)
at org.springframework.shell.standard.commands.GroupsInfoModel.lambda$of$3(GroupsInfoModel.java:74)
at java.base@17.0.7/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base@17.0.7/java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1850)
at java.base@17.0.7/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base@17.0.7/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base@17.0.7/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base@17.0.7/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base@17.0.7/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.springframework.shell.standard.commands.GroupsInfoModel.lambda$of$4(GroupsInfoModel.java:75)
at java.base@17.0.7/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base@17.0.7/java.util.TreeMap$EntrySpliterator.forEachRemaining(TreeMap.java:3287)
at java.base@17.0.7/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base@17.0.7/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base@17.0.7/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base@17.0.7/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base@17.0.7/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.springframework.shell.standard.commands.GroupsInfoModel.of(GroupsInfoModel.java:78)
at org.springframework.shell.standard.commands.Help.renderCommands(Help.java:129)
at org.springframework.shell.standard.commands.Help.help(Help.java:84)
at java.base@17.0.7/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.shell.command.invocation.InvocableShellMethod.doInvoke(InvocableShellMethod.java:306)
at org.springframework.shell.command.invocation.InvocableShellMethod.invoke(InvocableShellMethod.java:232)
at org.springframework.shell.command.CommandExecution$DefaultCommandExecution.evaluate(CommandExecution.java:222)
at org.springframework.shell.Shell.evaluate(Shell.java:246)
at org.springframework.shell.Shell.run(Shell.java:158)
at org.springframework.shell.jline.NonInteractiveShellRunner.run(NonInteractiveShellRunner.java:129)
at org.springframework.shell.DefaultShellApplicationRunner.run(DefaultShellApplicationRunner.java:65)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:760)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:750)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:317)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293)
at com.example.demo.DemoApplication.main(DemoApplication.java:17)