Skip to content

Annotated commands are not registered in GraalVM native binary #1229

@fmbenhassine

Description

@fmbenhassine

After fixing native runtime hints in 891a148, the native compilation now passes but the user's defined annotated commands are not discovered correctly:

package org.springframework.shell.samples.helloworld.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.shell.core.command.annotation.Option;

@SpringBootApplication
public class SpringShellApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringShellApplication.class, args);
	}

	@Command(name = "hello", description = "Say hello to a given name", group = "Greetings",
			help = "A command that greets the user with 'Hello ${name}!'. Usage: hello [-n | --name]=<name>")
	public void sayHello(@Option(shortName = 'n', longName = "name", description = "the name of the person to greet",
			defaultValue = "World") String name) {
		System.out.println("Hello " + name + "!");
	}

}

Here is a minimal complete app to use with GraalVM 25+ and the snapshots of Spring Shell v4 at 891a148 or later:

spring-shell-sample-spring-boot.zip

The following instructions can be found in the README of the attached minimal project:

$>sdk install java 25.0.1-graalce
$>sdk use java 25.0.1-graalce
$>java -version
openjdk version "25.0.1" 2025-10-21
OpenJDK Runtime Environment GraalVM CE 25.0.1+8.1 (build 25.0.1+8-jvmci-b01)
OpenJDK 64-Bit Server VM GraalVM CE 25.0.1+8.1 (build 25.0.1+8-jvmci-b01, mixed mode, sharing)
$>./mvnw clean install
$>./mvnw -Pnative native:compile

Once the native build is complete, run the native executable located in the target directory and see how the hello command does not show up:

$>./target/spring-shell-sample-spring-boot

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v4.0.1)

[...]

06:35:21.547 [main] INFO  o.s.s.s.h.b.SpringShellApplication - Started SpringShellApplication in 0.273 seconds (process running for 0.298)
shell:>help
06:35:26.760 [main] INFO  o.h.validator.internal.util.Version - HV000001: Hibernate Validator 9.0.1.Final
Available commands:
Built-In Commands
	clear: Clear the terminal screen
	help: Display help about available commands
	version: Show version info
	script: Execute commands from a script file

shell:>

Note that this issue happens only with annotated commands, commands created programmatically with Command.Builder and defined as beans are correctly registered:

package org.springframework.shell.samples.helloworld.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.core.command.Command;

@SpringBootApplication
public class SpringShellApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringShellApplication.class, args);
	}

	@Bean
	public Command sayHello() {
		return Command.builder()
				.name("hello")
				.group("Greeting Commands")
				.description("Say Hello")
				.execute(context -> { System.out.println("Hello, World!");});
	}

}

With this sample, the hello command is shown and runs as expected:

$>./target/spring-shell-sample-spring-boot

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v4.0.1)

16:09:54.040 [main] INFO  o.s.s.s.h.b.SpringShellApplication - Started SpringShellApplication in 0.277 seconds (process running for 0.304)
shell:>help
16:09:59.747 [main] INFO  o.h.validator.internal.util.Version - HV000001: Hibernate Validator 9.0.1.Final
Available commands:
Built-In Commands
	script: Execute commands from a script file
	version: Show version info
	clear: Clear the terminal screen
	help: Display help about available commands
Greeting Commands
	hello: Say Hello

shell:>hello
Hello, World!
shell:>exit
Exiting the shell
$>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions