-
Notifications
You must be signed in to change notification settings - Fork 396
Description
Before Spring Shell 4.0, boolean command options would default to false if not specified when executing the command. In 4.0, they fail instead with the following error message:
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [boolean] for value [null]
at org.springframework.core.convert.support.GenericConversionService.assertNotPrimitiveTargetType(GenericConversionService.java:300)
at org.springframework.core.convert.support.GenericConversionService.handleResult(GenericConversionService.java:293)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:182)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:165)
at org.springframework.shell.core.command.adapter.MethodInvokerCommandAdapter.prepareArguments(MethodInvokerCommandAdapter.java:166)
at org.springframework.shell.core.command.adapter.MethodInvokerCommandAdapter.doExecute(MethodInvokerCommandAdapter.java:90)
at org.springframework.shell.core.command.AbstractCommand.execute(AbstractCommand.java:162)
at org.springframework.shell.core.command.CommandExecutor.execute(CommandExecutor.java:71)
... 28 more
Caused by: java.lang.IllegalArgumentException: A null value cannot be assigned to a primitive type
... 36 more
So, a command definition like the following with Spring Shell 3.4:
@Command(name = "test", description = "Test command.")
public void build(
@Option(description = "Perform a clean build.") boolean clean,
) {
...
}would need to change to the following in 4.0:
@Command(name = "test", description = "Test command.")
public void build(
@Option(description = "Perform a clean build.", defaultValue = "false", longName = "clean") boolean clean,
) {
...
}That's counterintuitive because in Java the primitive type boolean is always false if unspecified.
Furthermore, when providing the option at execution time, a value is also required. This bit is mentioned in the docs, but it would be great to highlight that in the migration guide as a breaking change since it completely change the user experience.
It's common for CLIs to pass boolean options to a command without a value, meaning it's "true". Any chance the previous behaviour could be restored? This breaking change doesn't affect only developers when upgrading to 4.0, but also all users of CLIs implemented with Spring Shell, having to change commands like:
mycli test --cleanto:
mycli test --clean trueThis is where the check is implemented:
Lines 125 to 129 in 2a1f020
| if (shortName == ' ' && longName.isEmpty()) { | |
| throw new IllegalArgumentException( | |
| "Either shortName or longName (or both) must be provided for option on parameter '" | |
| + parameter.getName() + "'"); | |
| } |
I'm available to help with a potential PR.