[java] Parsing arguments to a Java command line program

I realize that the question mentions a preference for Commons CLI, but I guess that when this question was asked, there was not much choice in terms of Java command line parsing libraries. But nine years later, in 2020, would you not rather write code like the below?

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
import java.io.File;
import java.util.List;
import java.util.concurrent.Callable;

@Command(name = "myprogram", mixinStandardHelpOptions = true,
  description = "Does something useful.", version = "1.0")
public class MyProgram implements Callable<Integer> {

    @Option(names = "-r", description = "The r option") String rValue;
    @Option(names = "-S", description = "The S option") String sValue;
    @Option(names = "-A", description = "The A file") File aFile;
    @Option(names = "--test", description = "The test option") boolean test;
    @Parameters(description = "Positional params") List<String> positional;

    @Override
    public Integer call() {
        System.out.printf("-r=%s%n", rValue);
        System.out.printf("-S=%s%n", sValue);
        System.out.printf("-A=%s%n", aFile);
        System.out.printf("--test=%s%n", test);
        System.out.printf("positionals=%s%n", positional);
        return 0;
    }

    public static void main(String... args) {
        System.exit(new CommandLine(new MyProgram()).execute(args));
    }
}

Execute by running the command in the question:

java MyProgram -r opt1 -S opt2 arg1 arg2 arg3 arg4 --test -A opt3

What I like about this code is that it is:

  • compact - no boilerplate
  • declarative - using annotations instead of a builder API
  • strongly typed - annotated fields can be any type, not just String
  • no duplication - option declaration and getting parse result are together in the annotated field
  • clear - the annotations express the intention better than imperative code
  • separation of concerns - the business logic in the call method is free of parsing-related logic
  • convenient - one line of code in main wires up the parser and runs the business logic in the Callable
  • powerful - automatic usage and version help with the built-in --help and --version options
  • user-friendly - usage help message uses colors to contrast important elements like option names from the rest of the usage help to reduce the cognitive load on the user

The above functionality is only part of what you get when you use the picocli (https://picocli.info) library.

Now, bear in mind that I am totally, completely, and utterly biased, being the author of picocli. :-) But I do believe that in 2020 we have better alternatives for building a command line apps than Commons CLI.