How does command Availability work in Spring Shell, and how do you make a command temporarily unavailable?
answer
- Availability.available() / unavailable("reason")
- Convention: <command>Availability() method
- @ShellMethodAvailability to link by name/keys
- Unavailable = listed in help but refuses to run
- Checked per invocation, reflects live state
basics
~20 sYou provide a method returning Availability that returns Availability.available() or Availability.unavailable("reason"). Spring Shell links it by naming convention (commandNameAvailability) or via @ShellMethodAvailability. Unavailable commands still list in help but refuse to run with the reason.
solid answer
~40 sAvailability lets a command be enabled or disabled based on runtime state — for example a `download` command only works after `connect`. You write a no-arg method returning the `Availability` type: return `Availability.available()` to enable it, or `Availability.unavailable("you are not connected")` to disable it with an explanation. Spring Shell binds the availability method to the command in two ways: (1) by convention, a method named `<commandMethodName>Availability` (e.g. `download` -> `downloadAvailability`) is auto-detected; (2) explicitly with `@ShellMethodAvailability("methodRef")` on the command, or on the availability method pointing back at command names. An unavailable command still appears in `help` (listed as currently unavailable) but invoking it prints the reason and does not execute the body. This is evaluated per invocation, so it reflects current state.
code
java · 24 lines@ShellComponent
public class RemoteCommands {
private boolean connected = false;
@ShellMethod("Connect to the server")
public String connect() { connected = true; return "connected"; }
@ShellMethod("Download a file")
public String download(String path) { return "downloading " + path; }
// Convention: download -> downloadAvailability
public Availability downloadAvailability() {
return connected
? Availability.available()
: Availability.unavailable("you are not connected");
}
// Explicit form sharing one check across commands:
@ShellMethodAvailability({"upload", "sync"})
public Availability requiresConnection() {
return connected ? Availability.available()
: Availability.unavailable("you are not connected");
}
}go deeper
Aware that commands can be conditionally enabled.
Can write an availability method and return available()/unavailable().
Knows both wiring styles, per-invocation evaluation, and help behavior for unavailable commands.
Distinguishes availability (UX) from authorization; designs stateful command lifecycles and shared availability checks across a suite.
**The problem it solves.** Some commands only make sense in certain states. You do not want to scatter `if (!connected) return error;` guards through every method. Spring Shell's *availability* mechanism centralizes that: the framework asks "is this command available right now?" before running it and before letting the user rely on it. **The Availability type.** `org.springframework.shell.Availability` is a small value object with two factory methods: - `Availability.available()` — the command can run. - `Availability.unavailable(String reason)` — the command is disabled; `reason` should read grammatically after "this command is not available because ..." (e.g. `unavailable("you are not connected")`). **Wiring an availability method to a command.** Two approaches: 1. **Naming convention.** Declare a public no-arg method returning `Availability` named `<commandMethodName>Availability`. For a command method `download`, the method `downloadAvailability()` is automatically associated. No annotation needed. 2. **Explicit `@ShellMethodAvailability`.** Put `@ShellMethodAvailability("customCheck")` on the `@ShellMethod` to name the availability method, decoupling the names. Alternatively annotate the availability method itself with `@ShellMethodAvailability({"download", "upload"})` listing the command *keys* it governs — handy to share one check across several commands. Placing `@ShellMethodAvailability` at class level with no value can apply to all commands in the component. **Evaluation timing.** Availability is checked at invocation time (and used to render help state), so it reflects live state held in the bean (e.g. a `connected` field toggled by other commands). It is not a one-time startup decision. **User-visible behavior.** In `help`, unavailable commands are listed and marked as currently unavailable. If the user runs an unavailable command, Spring Shell does not execute the method body; it prints a message like "Command 'download' exists but is not currently available because you are not connected." and suggests checking availability. **Edge cases / gotchas.** - The availability method must return `Availability` and take no arguments; a wrong signature is silently not linked (nothing enforces the convention name matches a real command). - If both a conventionally named method and an explicit annotation exist, the explicit one wins. - Availability differs from *security/authorization*; it is UX-level gating, not an access-control boundary. - Because it reads mutable bean state, keep that state thread-consistent (the shell is typically single-threaded interactively, but scripts/async change that). **When to use.** Stateful CLIs (connect/disconnect, login/logout, load-a-file-then-operate), feature flags, or environment gating where you want clear, discoverable reasons rather than opaque failures.
- What are the two ways Spring Shell associates an availability method with a command?By naming convention (<commandMethod>Availability), or explicitly via @ShellMethodAvailability — on the command naming the method, or on the availability method listing the command keys it governs.
- Is availability a substitute for authorization?No. It is UX-level gating that hides/blocks commands with a reason. Real access control belongs in the underlying services/security layer; availability just improves discoverability and error messaging.
saying these in an interview costs you the question
- Claiming an unavailable command disappears from help (it is still listed, just marked unavailable)
- Thinking availability is evaluated once at startup rather than per invocation
- Treating availability as a security/authorization mechanism
- Giving the availability method arguments or a non-Availability return type