Repository navigation
Closed
Labels
type/bugIs a bug reportIs a bug report
Milestone
Description
Spring Boot 3.4.2
Spring Shell 3.4.0
JDK 17
Problem:
When using the @Command annotation on a component class, the Spring Shell fails to register the command, throwing an IllegalStateException with the message "No Command annotation found" in case of @EnableCommand usage and application runs without any errors, but commands are completely unregistered in case of @CommandScan usage.
Code:
CommandsNotation.java
import com.slezkipotekli.githubactivity.services.ActivityService;
import lombok.AllArgsConstructor;
import org.springframework.shell.command.annotation.Command;
import org.springframework.shell.command.annotation.Option;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class CommandsNotation {
ActivityService activityService;
@Command(command = "github-activity")
public String githubActivity(@Option(longNames = "username", required = false) String username ){
return activityService.get_activity(username);
}
}GithubActivityApplication.java
package com.slezkipotekli.githubactivity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.command.annotation.CommandScan;
import org.springframework.shell.command.annotation.EnableCommand;
@SpringBootApplication
// @EnableCommand(CommandsNotation.class) - Included every option I used for clarity
// @CommandScan - Included every option I used for clarity
// @CommandScan("com.slezkipotekli.githubactivity") - Included every option I used for clarity
public class GithubActivityApplication {
public static void main(String[] args) {
SpringApplication.run(GithubActivityApplication.class, args);
}
}Output:
With @EnableCommand(CommandsNotation.class)
2025-02-03T21:53:21.864-05:00 ERROR 11404 --- [github-activity] [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: No Command annotation found on 'com.slezkipotekli.githubactivity.CommandsNotation'.
at org.springframework.util.Assert.state(Assert.java:101) ~[spring-core-6.2.2.jar:6.2.2]
at org.springframework.shell.command.annotation.support.CommandRegistrationBeanRegistrar.registerCommandClassBeanDefinition(CommandRegistrationBeanRegistrar.java:91) ~[spring-shell-core-3.4.0.jar:3.4.0]
at org.springframework.shell.command.annotation.support.CommandRegistrationBeanRegistrar.register(CommandRegistrationBeanRegistrar.java:67) ~[spring-shell-core-3.4.0.jar:3.4.0]
at org.springframework.shell.command.annotation.support.CommandRegistrationBeanRegistrar.register(CommandRegistrationBeanRegistrar.java:61) ~[spring-shell-core-3.4.0.jar:3.4.0]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]With @CommandScan
:: Spring Boot :: (v3.4.2)
2025-02-03T21:56:03.757-05:00 DEBUG 9340 --- [github-activity] [ main] o.s.s.s.StandardMethodTargetRegistrar : Found commandBeans to register {help=org.springframework.shell.standard.commands.Help@2d7637e6, clear=org.springframework.shell.standard.commands.Clear@515b9d4a, quit=org.springframework.shell.standard.commands.Quit@39b626e5, stacktrace=org.springframework.shell.standard.commands.Stacktrace@32a4ecbe, script=org.springframework.shell.standard.commands.Script@2e71240b, historyCommand=org.springframework.shell.standard.commands.History@23cd5d42, version=org.springframework.shell.standard.commands.Version@2b44d6d0}
2025-02-03T21:56:03.769-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[help]' key='help'
2025-02-03T21:56:03.788-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with mp='method 'help' parameter 0' so='@org.springframework.shell.standard.ShellOption(optOut=false, arity=2147483647, help="The command to obtain help for.", valueProvider=org.springframework.shell.standard.CommandValueProvider.class, value={"-C", "--command"}, defaultValue="__NULL__")'
2025-02-03T21:56:03.789-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering o='-C' stripped='C'
2025-02-03T21:56:03.790-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering o='--command' stripped='command'
2025-02-03T21:56:03.790-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering longNames='[command]' shortNames='[C]'
2025-02-03T21:56:03.796-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[clear]' key='clear'
2025-02-03T21:56:03.797-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[quit, exit]' key='quit'
2025-02-03T21:56:03.798-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[stacktrace]' key='stacktrace'
2025-02-03T21:56:03.799-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[script]' key='script'
2025-02-03T21:56:03.800-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with mp='method 'script' parameter 0' so='null'
2025-02-03T21:56:03.800-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Using mp='method 'script' parameter 0' longName='file' parameterType='class java.io.File'
2025-02-03T21:56:03.801-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[history]' key='history'
2025-02-03T21:56:03.802-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with mp='method 'history' parameter 0' so='@org.springframework.shell.standard.ShellOption(optOut=false, arity=-1, help="A file to save history to.", valueProvider=org.springframework.shell.standard.ShellOption.NoValueProvider.class, value={}, defaultValue="__NULL__")'
2025-02-03T21:56:03.802-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Using mp='method 'history' parameter 0' longName='file' parameterType='class java.io.File'
2025-02-03T21:56:03.802-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering longNames='[file]' shortNames='[]'
2025-02-03T21:56:03.802-05:00 DEBUG 9340 --- [ main] o.s.s.s.StandardMethodTargetRegistrar : Registering with keys='[version]' key='version'
shell:>help
AVAILABLE COMMANDS
Built-In Commands
help: Display help about available commands
stacktrace: Display the full stacktrace of the last error.
clear: Clear the shell screen.
quit, exit: Exit the shell.
history: Display or save the history of previously run commands
version: Show version info
script: Read and execute commands from a file.
shell:>github-activity
No command found for 'github-activity'Metadata
Metadata
Assignees
Labels
type/bugIs a bug reportIs a bug report
Activity
sourabhsmf commentedon Feb 4, 2025
Ran into same issue, looks like it requires
@Commandannotation to be present on the class as well otherwise it does not register the command. It is not very clear when reading the documentation.fmbenhassine commentedon Apr 25, 2025
I confirm the issue, the following fails with
java.lang.IllegalStateException: No Command annotation found on 'demo.Main':And the following does not register the command as documented:
To me,
@Commandshould only target methods, not types. It is confusing to have to annotate a class with@Commandand also command methods with@Commandas well. I believe the main reason for that was to have parent/child relationship where one can define common attributes for all commands at the class level, but this should be done with another annotation or some other way. The second confusing behaviour is that some attributes have different meaning / behaviour depending on whether the annotation is present on a class or a method, like aliases for example.I believe this should be revisited and fixed, so I will plan it for the next major release.
Add hello world sample
fmbenhassine commentedon Nov 2, 2025
Related issue: #1206
fmbenhassine commentedon Dec 9, 2025
Resolved in 4.0.0-M2.
@EnableCommandis now only needed when using Spring Shell without Spring Boot.@CommandScanis not needed anymore. New samples with and without Spring Boot have been added to get started: