Overview

When developing Java application for command line interface (CLI), it’s essential to parse input argument correctly. However, you don’t want to reinvent the wheel because it’s not easy and you’ve more important tasks to do, right? In my own experience, I found Apache Commons CLI very useful. I used it when maintaining nuxeoctl, and when I developing command line tools for side-projects.

Today, I would like to introduce Apache Commons CLI to you. After reading this article, you will understand:

  1. Prerequisite
  2. How to create “options”
  3. How to create individual “option”
  4. How to parse command line arguments
  5. How to query the parsed result
  6. How to show usage and help

Prerequisite

If you want to use Apache Commons CLI in your Java project, you need to declared the following dependency in Maven:

<dependency>
  <groupId>commons-cli</groupId>
  <artifactId>commons-cli</artifactId>
  <version>1.4</version>
</dependency>

Or in Gradle:

commons-cli:commons-cli:1.4

Create Options

“Options” is the main entry-point of the library. “Options” represents a collection of “Option” objects, which describe the possible options for a command-line. It may flexibly parse long and short options, with or without values. Additionally, it may parse only a portion of a command line, allowing for flexible multi-stage parsing.

Options options = new Options();

Once done, you can add one or several new “Option” into “Options”, and parse “Options” afterwards.

Create Individual Option

“Option” describes a single command-line option. It maintains different information such as its short name, its long name, argument requirement, description etc. There are two ways to create a new option: via an instance of “Options”, or via option builder.

Create option via “Options”. Class org.apache.commons.cli.Options provides different methods for creating a new option. Here are some of the examples:

// Create an option with short name
// "-v" for enabling the verbose mode.
options.addOption("v", "Enable verbose mode");

// Create an option with short name
// "-f" for configuring filepath. It
// has an argument (hasArg=true).
options.addOption("f", true, "Config filepath");

// Create an option with short name
// "-i" or long name "--ignore", for
// specifying the case-sensitive case.
options.addOption("i", "ignore", false, "Ignore case");

Create option via builder. Class org.apache.commons.cli.Option.Builder can also be used to create an “Option” using descriptive methods.

Option opt = Option.builder("a")
    .longOpt("all")
    .desc("Display all")
    .build();
options.addOption(opt);

Parse Command Lines

Parsing command lines can be done by using CommandLineParser and an instance of “Options”. If the arguments are parsed successfully, the method will return an instance of “CommandLine”. Else, it will throw a checked exception.

public static void main(String[] args) {
  Options options = ...;
  CommandLineParser parser = new DefaultParser();
  try {
    CommandLine cmd = parser.parse(options, args);
  } catch (ParseException e) {
    // ...
  }
}

Query Command Line

Once you successfully created the command line instance, you can query it: to see if an option has been passed, or to retrieve the option value.

Query if the option exist:

if (cmd.hasOption("v")) {
  // enable verbose mode...
}

If exists, return the option value. Note that, if the option does not exist, the return value will be null. Be careful about NullPointerException

if (cmd.hasOption("f")) {
  String path = cmd.getOptionValue("f");
  // return null if the option does not
  // exist in command line
}

If your application support default value, you can give it to the method as the 2nd parameter:

String e = cmd.getOptionValue("encoding", "utf-8");

Use HelpFormatter to generate the help with usage. The layout of the help message looks like this:

header
-----
body (options)
-----
footer

By default, the header is the command line syntax, provided by user. The body is generated by the library. The footer is ignored.

HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("cmd", newOptions());
usage: cmd
 -a,--all      Display all
 -f <arg>      Config filepath
 -i,--ignore   Ignore case
 -v            Enable verbose mode

However, you can enable the auto-usage for header, so that the options generated and included in header.

formatter.printHelp("cmd", newOptions(), true);
usage: cmd [-a] [-f <arg>] [-i] [-v]
 -a,--all      Display all
 -f <arg>      Config filepath
 -i,--ignore   Ignore case
 -v            Enable verbose mode

Conclusion

In this article, we see how to create “Options” and “Option” in Apache Command CLI, how to parse “Options” using parser and exception handling, how to query the result (CommandLine), and print help and usage. The source code is available at mincong-h:blog/2019-08-06-cli, under directory “cli”. Hope you enjoy this article, see you the next time!

References