Java Command-Line Interfaces (Part 7): JCommander
This is the seventh post in my series that briefly introduces various libraries for processing command-line arguments in Java. This post returns to coverage of an annotation-based library that seems to be one of the better known and more popular of the numerous available libraries for processing command line arguments from Java: JCommander.
JCommander‘s web page states, “Because life is too short to parse command line parameters” and the Overview introduces JCommander as “a very small Java framework that makes it trivial to parse command line parameters.” The code examples and associated screen snapshots of the executing code in this post are based on JCommander 1.72 (June 2017). The full code for the demonstrations shown here is available on GitHub.
JCommander uses annotations to implement the “definition” stage of command-line processing. This is demonstrated in the next code listing snippet.
“Definition” Stage with JCommander
/** * Demonstrates use of JCommander for Java-based command-line processing. */ public class Main { @Parameter(names={"-v","--verbose"}, description="Enable verbose logging") private boolean verbose; @Parameter(names={"-f","--file"}, description="Path and name of file to use", required=true) private String file; @Parameter(names={"-h", "--help"}, description="Help/Usage", help=true) private boolean help; // . . . final JCommander commander = JCommander.newBuilder() .programName("JCommander Demonstration") .addObject(this) .build();
The just-shown code listing demonstrates use of JCommander’s @Parameter annotation to define the command-line options via annotation of class fields. The examples demonstrate specification of names
to indicate multiple option flags to be associated with a single option, description
to provide a description of each option, required=true
to enforce presence of a command-line argument, and help=true
to indicate a “help” or “usage” command-line argument (instructs JCommander to not throw exception if required arguments are not also provided).
With the class attributes annotated with @Parameter
annotations, an instance of the class with annotated fields can be used to create an instance of the JCommander class. In the code example above, I took advantage of the JCommander.Builder for the greater fluency and other advantages associated with use of builders. In particular, the instance with annotated class fields is added via the addObject(Object) method.
The “parsing” stage of command-line processing with JCommander is accomplished via a single line invocation of the parse(String…) method on the instance of JCommander
that was just instantiated. This is demonstrated in the next code listing.
“Parsing” Stage with JCommander
commander.parse(arguments);
The “interrogation” stage of command-line processing with JCommander involves simply accessing the annotated fields of the instance passed to the JCommander
class instantiation. This is demonstrated in the next code listing.
“Interrogation” Stage with JCommander
if (help) { commander.usage(); } else { out.println( "The file name provided is '" + file + "' and verbosity is set to " + verbose); }
The last code listing demonstrates the ability to determine if the boolean
attribute with name help
was set by the specification of --help
or -h
. Because it’s a simple boolean
, it can be used in the conditional and, if true
, the help/usage information is presented. In the case when the “help” flag was not set, values associated with the other command line options (“verbose”/-v
/--verbose
and “file”/-f
/--file
) are accessed.
The most recent code listing also demonstrates writing the usage information to standard output via an invocation of the method usage() on the instance of the JCommander
class. It’s worth noting that ParameterException
also has a usage() method.
The next series of screen snapshots demonstrate using JCommander with a simple application that includes the above code snippets. The first image shows running the JCommander-based application without any arguments and shows the ParameterException that is displayed in that case because the required --file
/-f
option was not specified.
The next screen snapshot demonstrates “normal” execution when the expected command line arguments are provided.
The next screen snapshot demonstrates use of the “help” option. Because this was annotated with help=true
, the absence of the required “file” command-line argument does not lead to an exception and the automatically generated help/usage information is written to standard output.
JCommander provides a feature that I really like for developing with and learning JCommander. One can specify increased verbosity of the JCommander parsing by invoking the method verbose(int) on JCommandBuilder.
Increasing JCommander’s Verbosity
final JCommander commander = JCommander.newBuilder() .programName("JCommander Demonstration") .addObject(this) .verbose(1) .build();
With the increased verbosity, greater insight into what JCommander is doing related to command-line processing can be discovered and this is demonstrated in the following two screen snapshots.
Here are some additional characteristics of JCommander to consider when selecting a framework or library to help with command-line parsing in Java.
- JCommander is open source and licensed with the Apache License 2.0.
- The
jcommander-1.72.jar
is approximately 68 KB in size and has no third-party library compile dependencies. - The JCommander documentation provides examples of using JCommander with Kotlin and using JCommander with Groovy.
- JCommander is still actively supported by TestNG creator Cedric Beust and its web page reflects its modern/current support.
Additional References
- JCommander
- JCommander on Maven Repository
- JCommander Source on GitHub
- JCommander API (Javadoc)
- Complex line command syntaxes with JCommander
- JCommander – parsing command line parameters with ease
- Easy Command Line Interface coding with JCommander
- Args4j vs JCommander for Parsing Command Line Parameters
- Java Command Line Flags with JCommander and Spring
- JCommander Versus args4j
Reference: | Java Command-Line Interfaces (Part 7): JCommander from our JCG partner Dustin Marx at the Inspired by Actual Events blog. |