Java command line parsing libraries compared

Java command line parsing libraries compared

This is a small comparison of command line parsing libraries in Java. It is not meant to be complete, but shall help people to find the best library for their needs.

What types are there?

There are basically two different types of librarys.No type is better than the other. It’s a question of personal preference what you like.

The types are exaplained in the next two subsections.

Builder style

The following example shows the builder style approach.

// create Options object
Options options = new Options();

// add t option
options.addOption("t", false, "display current time");

The possible command line parameters are defined by creating an object tree. In the example, a generic Options object is created and an option is added using a method invocation.

After parsing, the command line options are queried from a generic command line holder object:

CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse( options, args);

if(cmd.hasOption("t")) {
    // print the date and time
}

The example shows the very popular library Apache Commons CLI.

Annotation style

The following example shows the annotation style approach:

public class Args {
  @Parameter
  private List<String> parameters = new ArrayList<>();

  @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
  private Integer verbose = 1;

  @Parameter(names = "-groups", description = "Comma-separated list of group names to be run")
  private String groups;

  @Parameter(names = "-debug", description = "Debug mode")
  private boolean debug = false;
}

The possible command line parameters are Java fields that are annotated with additional information for the command line parsing library.

The parsing results are written by the library in an instance of the  annotated class (in this case Args) itself:

Args args = new Args();
String[] argv = { "-log", "2", "-groups", "unit" };
JCommander.newBuilder()
  .addObject(args)
  .build()
  .parse(argv);

Assert.assertEquals(args.verbose.intValue(), 2);

The example shows the quite popular JCommander library.

Comparison table

The following table shows a selection of libraries that can be downloaded and are more or less actively maintained.

I have not included libraries that are obviously not maintained anymore for multiple years.

LibraryLicenseTypeLivenessMin JDK Artifact
Args4JMITAnnotationMedium (10 months)6artifact
JCommanderApache 2.0AnnotationHigh (20 days)7artifact
Apache Commons CLIApache 2.0BuilderMedium (8 months)5artifact
JArgsBSD-3BuilderVery low (5 years)5?
JOptSimpleMITBuilderMedium (3 months)8artifact
JewelCLIApache 2.0AnnotationVery low (3 years)6artifact
PicoCLIApache 2.0AnnotationHigh (5 days)5artifact

About the columns

The following is the description of the columns used in the table.

  • Library: Tells the library name and links to the library development site.
  • License: States which software license the library is developed under.
  • Type: The API approach this library takes. Annotation means the library uses Java annotations to document the command line options. Builder means the user needs to actively build a command line object model in code.
  • Liveness: How much is this library alive? When was the last release or accepted pull request? A library that is not changed for a long time is unlikely to receive support or bug fixes.
  • Min JDK: The minimum JDK version needed to use this library. If you are forced to use an old JDK, this can be very important.
  • Artifact: A link to an artifact that is usable by building tools like Maven or Gradle. It can be ugly to include a jar file library into a Maven-based project.

What else could be interesting?

  • Test coverage of the code: The more tests there are, the more stable and robust the library is.
  • Number of dependencies: If you need to take a look at the disk footprint, you should stick to a library that has only a few or no dependencies.

Recommendation

I won’t recommend a certain library for you. You should decide what library you can use at all regarding the hard facts (Min JDK, license, liveness). Regarding the type of library it’s a matter of taste.

Annotation based

I personally prefer Annotation based libraries and have contributed to the args4j project in the past. Unfortunately it looks like the author is busy with other stuff at the moment. This is why I chose JCommander for the annotation examples which is a very lively project.

PicoCLI looks like a promising newcomer with a very good documentation. Because of the coloring of the command line it doesn’t look very pico to me, more mini.

Builder based

Apache Commons CLI is the indestructable evergreen with the builder approach that has been used by thousands of projects.

Further reading

I’ve started an open source project called args2all that reads annotated classes for multiple libraries and generates Markdown or manpage documentation for them.