1. Registration

There are two different ways to define a command: through an annotation model and through a programmatic model. In the annotation model, you define your methods in a class and annotate the class and the methods with specific annotations. In the programmatic model, you use a more low level approach, defining command registrations (either as beans or by dynamically registering with a command catalog).

1.1. Annotation Model

When you use the standard API, methods on beans are turned into executable commands, provided that:

  • The bean class bears the @ShellComponent annotation. (This is used to restrict the set of beans that are considered.)

  • The method bears the @ShellMethod annotation.

The @ShellComponent is a stereotype annotation that is itself meta-annotated with @Component. As a result, you can use it in addition to the filtering mechanism to declare beans (for example, by using @ComponentScan).

You can customize the name of the created bean by using the value attribute of the annotation.

@ShellComponent
static class MyCommands {

	@ShellMethod
	public void mycommand() {
	}
}

The only required attribute of the @ShellMethod annotation is its value attribute, which should have a short, one-sentence, description of what the command does. This lets your users get consistent help about your commands without having to leave the shell (see [built-in-commands-help]).

The description of your command should be short — no more than one or two sentences. For better consistency, it should start with a capital letter and end with a period.

By default, you need not specify the key for your command (that is, the word(s) that should be used to invoke it in the shell). The name of the method is used as the command key, turning camelCase names into dashed, gnu-style, names (for example, sayHello() becomes say-hello).

You can, however, explicitly set the command key, by using the key attribute of the annotation:

@ShellMethod(value = "Add numbers.", key = "sum")
public int add(int a, int b) {
	return a + b;
}
The key attribute accepts multiple values. If you set multiple keys for a single method, the command is registered with those different aliases.
The command key can contain pretty much any character, including spaces. When coming up with names though, keep in mind that consistency is often appreciated by users. That is, you should avoid mixing dashed-names with spaced names and other inconsistencies.

1.2. Programmatic Model

In the programmatic model, CommandRegistration can be defined as a @Bean and it will be automatically registered.

@Bean
CommandRegistration commandRegistration() {
	return CommandRegistration.builder()
		.command("mycommand")
		.build();
}

If all your commands have something in common, an instance of a CommandRegistration.BuilderSupplier is created which can be autowired. Default implementation of this supplier returns a new builder so you don’t need to worry about its internal state.

Commands registered programmatically automatically add help options mentioned in [commands-helpoptions].

If bean of this supplier type is defined then auto-configuration will back off giving you an option to redefine default functionality.

@Bean
CommandRegistration commandRegistration(CommandRegistration.BuilderSupplier builder) {
	return builder.get()
		.command("mycommand")
		.build();
}

CommandRegistrationCustomizer beans can be defined if you want to centrally modify builder instance given you by supplier mentioned above.

@Bean
CommandRegistrationCustomizer commandRegistrationCustomizerExample() {
	return builder -> {
		// customize instance of CommandRegistration.Builder
	};
}