Monday 10 February 2014

Command Line Application Start

Java has the 'main' method to start its apps and this is very easy to invoke.  However, there are times when optional arguments need to be passed into the app and for this the apache commons cli (Command Line Interface) is really useful.

Creating a Parser

Creating a parser is really simple and involves just one line

    CommandLineParser parser = new BasicParser();

Creating Options

The options for the command line are built using a builder pattern.  Here is an example

    OptionBuilder
        // the name of the argument
        .withArgName("timeout") 
        // this has two arguments -timeout <value>
        .hasArgs(2)
        // the separator '-' is used
        .withValueSeparator()
        // the description used for the help text
        .withDescription("Millisecond timeout for this test (default: 20000)")
        // create this option refered to as 'timeout'      
        .create("timeout")

This option is then added to the list of options

    final Options options = new Options();
    options.addOption(OptionBuilder.withArgName(.......));

which are added to the parser

    CommandLine line = parser.parse(options, args);

Getting the values

This CommandLine object can then be used to get the values that have been provided.

    final String timeoutStr = line.getOptionValue("timeout", "20000");

or query that an option has been provided,

    if (line.hasOption("timeout")) {
    
    }

Help Text
The descriptions created in the Options can be used to generate help text

    final HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("sample", options);

which is useful if a value fails validation or particular options are not provided.

Example

Here is a full example

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class SampleMain
{


    /**
     * Main.
     * 
     * @param args The command line args
     */
    public static void main(final String[] args)
    {

        final CommandLineParser parser = new BasicParser();
        final Options options = new Options();
        options.addOption(OptionBuilder.withArgName("timeout").hasArgs(2).withValueSeparator()
                .withDescription("Millisecond timeout for this app (default: 20000)").create("timeout"));
        options.addOption(OptionBuilder.withArgName("filepath").hasArgs(2).withValueSeparator()
                .withDescription("Configuration file").create("filepath"));
        options.addOption(OptionBuilder.withArgName("logdirectory").hasArgs(2).withValueSeparator()
                .withDescription("log directory (default: ./logs)").create("logdirectory"));
        
        CommandLine line = parser.parse(options, args);
        
        // Get the timeout
        final String timeoutStr = line.getOptionValue("timeout", "20000");
        final long timeout = Long.valueOf(timeoutStr);

        // Log directory for the app
        final String logDirectory = line.getOptionValue("logdirectory", "./logs");
        
        if (line.hasOption("filepath"))
        {
            // Do something with this file
        }
        else
        {
            final HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("sample", options);
        }
    }
}

Use

This code would then be used,

    java -jar sample.jar -logdirectory ./mylog -timeout 5000 -filepath mydir/myfile

or to use the defaults

    java -jar sample.jar -filepath mydir/myfile