Apache commons CLI not parsing as expected?

2019-09-14 16:09发布

问题:

public static void main(String[] args) {

    Options options = new Options();
    Option hostOption = Option.builder("h")
            .longOpt("host")
            .required(false)
            .build();

    Option portOption = Option.builder("p")
            .longOpt("port")
            .required(false)
            .type(Number.class)
            .build();

    Option serviceNameOption = Option.builder("n")
            .longOpt("service_name")
            .required(false)
            .build();

    options.addOption(hostOption);
    options.addOption(portOption);
    options.addOption(serviceNameOption);

    String serviceName = "dbservice"
    String host = "localhost";
    int port = 7512;
    CommandLineParser parser = new DefaultParser();
    Server server = new Server();
    try {
        CommandLine cmd = parser.parse(options, args);
        if(cmd.hasOption("host")) {
            host = cmd.getOptionValue("host");
            System.out.println(host); //gets in here but prints null
        }
        if (cmd.hasOption("port")) {
            port = ((Number)cmd.getParsedOptionValue("port")).intValue();
            System.out.println(port); // gets in here but throws a null pointer exception

        }
        if (cmd.hasOption("service_name")) {
            serviceName = cmd.getOptionValue("service_name");
            System.out.println(serviceName); // gets in here but prints null
        }
    } catch(Exception e) {}
 }

I am using Apache commons cli library to parse command line args however it doesn't seem to parse as expected. Not sure what I am missing here?

I invoked in many different way just to see if it works and the below is one of them java -jar dbservice.jar --host localhost --port 7514. What is the right way to invoke anyway? I dont see that in the documentation

回答1:

In order for the Option to accept an argument, the hasArg(true) must be passed to the builder. For each of the options, add a ".hasArg(true)". Modifying your code with this argument and running a test case resulted in the expected output.

    Option hostOption = Option.builder("h")
        .longOpt("host")
        .required(false)
        .hasArg(true)
        .build();


回答2:

For the first time users, hasArg() is confusing, you would assume by default, that without specifying hasArg(), at least one argument will be taken to create an option. Passing a value '--opt val' without hasArg() silently ignores the val as if nothing is passed, well, if no hasArg() is specified then it should fail because something was passed instead of ignoring. May be, there should be a strict mode?