Featured Post

Applying Email Validation to a JavaFX TextField Using Binding

This example uses the same controller as in a previous post but adds a use case to support email validation.  A Commons Validator object is ...

Saturday, November 8, 2014

Handling Command Line or JNLP Arguments in Java

If you have a single option that you'd like to pass with your main(), get it using the args String array (arg[0]).  If you have more than one option, consider using the Commons Cli library.  Commons Cli let's you handle any number of options including those with arguments.  Additionally, the command line will be less brittle because order isn't important.

Without Commons Cli

Without Commons Cli, you might do something like this to retrieve a single option from the command line or JNLP argument

public static void main(String[] args) throws ParseException {

String useHidpi = args[0];
if( StringUtils.equalsIgnoreCase(useHidpi, "hidpi") ) {
System.out.println("using hidpi option");
} else {
System.out.println("not using hidpi");
}
}

If you need add a second option, extending this pattern might be problematic.  That's because the ordering of the second option -- or whether a first option is even specified -- would need to be handled by you.

Commons Cli

This code considers two options: hidpi and jnlp.  Neither parameter is required. Some possible calls are

$ java CliTest
$ java CliTest -hidpi
$ java CliTest -jnlp
$ java CliTest -hidpi -jnlp
$ java CliTest -jnlp -hidpi
$ java CliTest -help

The last call is important because it's often the first thing run when working with a new command.

To implement this, you add the Maven dependency "Commons Cli".

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

And in your code, you set up an Options data structure.  Each Option object consists of the option ("help" is "-help", "hidpi" is "-hidpi"), a flag about whether or not it accepts an argument, and a message to be used in the help function.

public static void main(String[] args) throws ParseException {

Options options = new Options();
options.addOption( "help", false, "Print this message");
options.addOption( "hidpi", false, "Use high-DPI scaling");
options.addOption( "jnlp", false, "Use JNLP muffins for persistence");
CommandLineParser p = new BasicParser();
CommandLine cmd = p.parse(options, args);
HelpFormatter formatter = new HelpFormatter();
if( cmd.hasOption("help") ) {
formatter.printHelp( "CliTest", options );
return;
}
if( cmd.hasOption("hidpi") ) {
System.out.println("using hidpi option");
} else {
System.out.println("not using hidpi");;
}
if( cmd.hasOption("jnlp") ) {
System.out.println("using jnlp option");
} else {
System.out.println("not using jnlp");;
}

}

Once the Options are setup, the String[] from main() or the Application.Parameters from a JavaFX start() are parsed.  I added a HelpFormatter to provide an extra option of "-help" for the end user.  Then, the CommandLine object is interrogated and my logic called.

Here are the results of some commands.  First no args

$ java CliTest
not using hidpi
not using jnlp

Next, help

$ java CliTest -help
usage: CliTest
 -help    Print this message
 -hidpi   Use high-DPI scaling
 -jnlp    Use JNLP muffins for persistence

Only one option set

$ java CliTest -hidpi
using hidpi option
not using jnlp

Both set.  This is the same output if I reverse the options "-jnlp -hidpi".

$ java CliTest -hidpi -jnlp
using hidpi option
using jnlp option

Here's a snippet of this in use in a JNLP file.

    <application-desc
         name="Maven POM Updater Application"
         main-class="com.bekwam.mavenpomupdater.Main"
         width="1920"
         height="1080">
      <argument>-hidpi</argument>
     </application-desc>

With a single option, args[0] is fine to interrogate.  However, if you're working with Maven already, pull in the Commons Cli library for anything more than a single option.  It is easy to work with the standard String array, but the simple API of Commons Cli will handle a lot of boundary cases with a minimum of impact to your project and a small learning curve.

1 comment: