I recently had to build a Spring Boot command line application whose application context depends on command line options. I specified the qualified property names (i.e., "<prefix>.<prop-name>" as option alias names using the OptionParser#addAll(List<String>) method of JOpt's fluent interface. I injected a customized StandardEnvironment with a JOptCommandLinePropertySource based on the parsed command line arguments into the SpringApplication. To my surprise, however, some of the properties were never bound to the corresponding @ConfigurationProperties object.
I found that this was caused by the implementation of JOptCommandLinePropertySource#getPropertyNames(): A comment in the source code claims "only the longest name is used for enumerating". However, the implementation always returns the last element of OptionSpec#options(). This is, in general, not the longest option name, because OptionSpec#options()
- first clusters the option names into short and long options and
- then sorts these groups lexicographically, respectively.
For some options, JOptCommandLinePropertySource#getPropertyNames() therefore contained the qualified alias name required for binding the property to the @ConfigurationProperties object, while for other options it contained the unqualified option alias. Admittedly, the documentation of JOptCommandLinePropertySource never specifies which property names are enumerated; but I can't see a scenario where the current behavior is useful.
This ticket's reference URL points to a JUnit class that demonstrates this behavior. The test class also includes alternative property name selection strategies that would work better in my scenario. (I wonder why JOptCommandLinePropertySource#getPropertyNames() needs to filter the option alias names in the first place.)