I am building a command-line Java application and I have a problem with parsing the command line parameters with Apache Commons CLI.
I am trying to cover my scenario where I need to have two exclusive command-line param groups with long (--abc) and short (-a) arguments as well.
Use case 1
- short params:
-d oracle -j jdbc:oracle:thin:@//host:port/databa - same but with long params:
-dialect oracle -jdbcUrl jdbc:oracle:thin:@//host:port/databa
Use case 2:
- short params:
-d oracle -h host -p 1521 -s database -U user -P pwd - same but with long params:
-dialect oracle -host host -port 1521 -sid database -user user -password pwd
So I created two OptionGroup with the proper Option items:
OptionGroup jdbcUrlGroup = new OptionGroup();
jdbcUrlGroup.setRequired(true);
jdbcUrlGroup.addOption(jdbcUrl);
second group:
OptionGroup customConfigurationGroup = new OptionGroup();
customConfigurationGroup.setRequired(true);
customConfigurationGroup.addOption(host);
customConfigurationGroup.addOption(port);
customConfigurationGroup.addOption(sid);
customConfigurationGroup.addOption(user);
customConfigurationGroup.addOption(password);
Then I build the Options object this way:
Options options = new Options();
options.addOptionGroup(jdbcUrlGroup);
options.addOptionGroup(customConfigurationGroup);
options.addOption(dialect);
But this does not work because it expects to define both groups.
This is how the dialect Option is defined:
Option dialect = Option
.builder("d")
.longOpt("dialect")
.required(false)
.hasArg()
.argName("DIALECT")
.desc("supported SQL dialects: oracle. Default value: oracle")
.build();
The other mandatory Option definitions look similar except this one property:
.required(true)
Result:
-d oracle: Missing required options: [-j ...], [-h ..., -p ..., -s ..., -U ..., -P ...]-d oracle -jdbcUrl xxx: Missing required option: [-h ..., -p ..., -s ..., -U ..., -P ...]-d oracle -h yyy: Missing required option: [-j ...]
But what I want is the following: if the JDBC URL is provided then the host, port, etc, params are not needed or the opposite.
I think that it is time to forget Apache Commons CLI and mark it as a deprecated library. Okay, if you have only a few command-line arguments then you can use it, otherwise better not to use. Fact that this Apache project was updated recently (17 February 2019), but still many features are missing from it and a little bit painful to work with Apache Commons CLI library.
The picocli project looks like a better candidate for parsing command line parameters. It is a quite intuitive library, easy to use, and has a nice and comprehensive documentation as well. I think that a middle rated tool with perfect documentation is better than a shiny project without any documentation.
Anyway
picocliis a very nice library with perfect documentation, so I give double plus-plus to it :)This is how I covered my use cases with
picocli:And this is how the generated help looks like:
This look is much better than the Apache CLI generated help.