spring-shell
spring-shell copied to clipboard
required Boolean with non-default value
spring shell version: 3.1.6
In one of my commands, I want to make sure that the end-user specifically indicates whether they either want A or B by using a Boolean. I don't want to make the choice for the end user.
When I add the following @Option on my command:
@Option(required = true, description = "Description", longNames = "Some long name") Boolean booleanOption
Spring Shell, automatically transforms the booleanOption to defaultValue false. The help menu of the command indicates that the booleanOption is optional.
When transforming into
@Option(required = true, description = "Description", longNames = "Some long name") boolean booleanOption
Still, the help menu indicates the booleanOption as optional. I assume for 2 reasons that this should not be the case: (1) it is a boolean and not Boolean. (2) required is explicitly set to true. The defaultValue is again false.
Setting the defaultValue to 'true' explicitly seems to be working.
@Option(required = true, description = "Description", longNames = "Some long name", defaultValue = "true")boolean booleanOption
It will show that the boolean is optional, but the default value will be true.
But again, I didn't want to choose for the user. I want the end user to articulate their choice when doing a command specifically.
If I write:
@Option(required = true, description = "Description", longNames = "Some long name", defaultValue = "")Boolean booleanOption
Or
@Option(required = true, description = "Description", longNames = "Some long name", defaultValue = "null")Boolean booleanOption
The defaultValue still translates to false (while as a Boolean I would expect it to be able to be null).
Is this the intended behavior?
Boolean/boolean values have a lot of baggage to keep backward compatibility for old versions. Essentially both boolean/Boolean are threaded same and I think it's Boolean.parseBoolean(String) where real value comes from.
At some point we did think if defaultValue should be Object and not a String as that would have then open a ways to possibly define "null" or effectively "null". But as we wanted to mimic what comes from terminal(which is always a string) we weren't sure of Object type would open a can of worms.
So essentially you'd like to have way for Boolean type to be null indicating that user didn't define an option?
I understand. I am sure adapting the above-mentioned example to take a String, like:
@Option(required = true, description = "Description", longNames = "Some long name") String booleanOption
could work as a solution. I do believe that using Boolean/boolean makes the code more readable, but that is an entirely other conversation.
I do think there are still 2 issues then:
- when using a
boolean(and not aBoolean), with the aforementioned@Option, if I remember correctly, Spring Shell still seems to indicate the boolean as optional. This seems, in the first place, to conflict withboolean, which can not or should not be null. Second it conflicts with the explicitly settingrequiredto true (see the initial example). - Maybe the documentation could be elaborated further. Currently, it says: "Using boolean types is a bit more involved as there are boolean and Boolean where latter can be null. Boolean types are usually used as flags meaning argument value may not be needed.", which made me assume that Boolean values can be optional, and boolean values should never be optional.
Feel free to correct me at any point. I am sure there is a history behind all these decisions, that I am not aware of. Let me know if I can help with anything.