1

I have a requirement to run a program where the runtime arguments are passed in the form,

--argumentName=argumentVaue

and I need to get those values in my main function shown below,

public class TestArguments {

  public static void main(String[] args) {

    System.out.println(System.getProperty("argumentA"));
    System.out.println(System.getProperty("argumentB"));
    System.out.println(System.getProperty("argumentC"));
    System.out.println(System.getProperty("argumentD"));

    for(int i=0; i<args.length; i++) {
        System.out.println("Argument " + i + " equals " + args[i]);
    }

  }

}

When I go through the values in args I just get one big string such as --argumentA=foo. I could just do a string.split("=") to separate the name from the value but this doesn't seem like an elegant way to get the argument values by their name. I thought System.getProperty("argumentName") would do the trick but the values are always null. I'm running my program through a jar like so java -cp "myProgram.jar" com.foo.bar.TestArguments --argumentA=a --argumentB=b --argumentC=c--argumentD=d.

1

2 Answers 2

2

Actually you pass program arguments as you pass them after the class to start :

"java -cp myProgram.jar" com.foo.bar.TestArguments --argumentA=a --argumentB=b --argumentC=c--argumentD=d.

The System.getProperty(String) methods allows to retrieve a system property, which is a different thing. That's why you don't retrieve program arguments by using this method.

System properties are properties of the system (the OS).
You can pass/create additional of them by passing them as JVM argument (and not program argument) and retrieve them more easily in your program:

java -DargumentA=a -DargumentB=b -DargumentC=c -DargumentD=d -cp 
    "myProgram.jar" com.foo.bar.TestArguments 

But it is rather misleading of bypassing by System properties to ease the retrieval of arguments that are specific to the program.

So keep your program arguments and rather than splitting the String args, use an API to do that.
Arg4J is very fine to achieve it.

It would be as simple as :

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionHandlerFilter;

public class TestArguments {

    @Option(name = "--argumentA", usage = "...")
    private String argumentA;

    @Option(name = "--argumentB", usage = "...")
    private String argumentB;

    @Option(name = "--argumentC", usage = "...")
    private String argumentC;

    @Option(name = "--argumentD", usage = "...")
    private String argumentD;

    public static void main(String[] args) throws IOException {
       new TestArguments().doMain(args);
       // run the logic of the program
    }

    public void doMain(String[] args) throws IOException {
      CmdLineParser parser = new CmdLineParser(this);

      try {
        // parse the arguments.
        parser.parseArgument(args);        
       } catch (CmdLineException e) {
         System.err.println(e.getMessage());
         parser.printUsage(System.err);
         return;
       }     
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

You answer is good as well, sorry I can only accept one answer and I went with the Apache Commons CLI. The annotations are nice though. Thank you.
@Mr. Tea You are welcome. Don't worry, it is not a problem :) As said in the comment of the answer, I find personally The Apache Commons CLI (that I used and didn't use for new applications) less practical than Args4J.
1

You could also use Apache Commons CLI which is a very nice library for parsing the command line.

You can use it in a Maven or Gradle project.

In a Gradle project you would need to insert this into the dependencies:

compile group: 'commons-cli', name: 'commons-cli', version: '1.4'

Here is an example of how you can implement this parameter (--argumentName=argumentValue) in Apache Commons CLI:

import org.apache.commons.cli.*;

public class CLITestMain {

    public static void main(String[] args) throws ParseException {
        // create Options object
        Options options = new Options();

        // add a option
        options.addOption("a", "argumentName", true, "Do something");
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse( options, args);

        if(cmd.hasOption("a")) {
            System.out.println("You nailed it!");
            System.out.println(cmd.getOptionValue("a"));
        }
        else {
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp( "CLITestMain", options );
        }
    }
}

This example supports a short form for the argument and a long form out of the box.

Long form:

java CLITestMain --argumentName=hi

Short form:

java CLITestMain -a=hi

3 Comments

I find personally The Apache Commons CLI (that I used and didn't use for new applications) less practical as Args4J. The API is really cumbersome.
@Mr.Tea In case the user did not enter the parameters correctly, you can actually use the HelpFormatter to auto generate the help message. See example above.
@gil.fernandes the HelpFormatter is a nice touch, just added it in, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.