1

I am working with JCommander 1.48, and i came across the following problem:

For Example I have got these Parameters:

@Parameter(names = "user", description = "the User")
private String user;
@Parameter(names = "password", description = "the password")
private String password

I am running my program with the following arguments:

--user hugo --password secret

and:

--user hugo david --password secret

Both of them amount to the same solution, the program is running perfectly. But I want the program to throw an Exception if there are too many values for a parameter. Iam aware of "arity"( amount of values for parameter ) as a configuration of the @Parameter annotation, but the default value of arity for Strings is 1 allready. It seems like everything is just getting ignored after the first value, as long as it is not another parameter.

Any solutions or ideas?

EDIT:

The Basic Solution (posted by assylias) does not work for me. More accurate Example:

public class MyTestProgram {
    private final Params options;
    public MyTestProgram(String[] args) {
        options = new Params();
        new JCommander(options).parse("--user hugo david --password secret".split(" "));
        //pass "args" to parse() instead of hardcoded string.
    }

    public static void main(String[] args) throws Exception {
        System.setProperty("org.jboss.logging.provider", "slf4j");
        new MyTestProgram(args);
    }
}

public class Params {
    @Parameter
    private List<String> parameters = new ArrayList<>();
    @Parameter(names = "--user", description = "the user", required = true)
    private String webuser;
    @Parameter(names = "--password", description = "the password", required = true)

    private String stage;
    //getters and setters
}

This is everything that happens before the actual program-code starts.

EDIT: assylias updated answer solved the problem.

leif_good
  • 376
  • 6
  • 19

2 Answers2

2

The program below throws an exception as you require:

class Params {
  @Parameter(names = "--user", description = "the User")
  String user;
  @Parameter(names = "--password", description = "the password")
  String password;

}

public static void main(String[] args) {
  Params p = new Params();
  new JCommander(p).parse("--user hugo  david --password secret".split(" "));
  System.out.println(p.user);
  System.out.println(p.password);
}

If you remove david the program prints hugo and secret as expected.


Update

In the code you posted, you have this:

@Parameter
private List<String> parameters = new ArrayList<>();

If you read the javadoc for the names attribute of the Parameter annotation, you will see (emphasis mine) that it is:

An array of allowed command line parameters (e.g. "-d", "--outputdir", etc...). If this attribute is omitted, the field it's annotating will receive all the unparsed options.

So the command "david" ends up in the parameters list. If you want an exception instead, you need to remove that parameter.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • I copied ur Code into a Testproject, just to check out if it is working for me too. Yes, your code works independent from my code. Unfortunately i was basically doing the same (changed from "JCommander(params, args)" to JCommander(params).parse(args)), which makes no difference at all, at least for my code. Why is my code not throwing this exception for me? I edited the question. As far as i can gather iam doing pretty much the same. – leif_good Dec 03 '15 at 15:16
0

According to the JCommander documentation, you can add custom parameter validations such as:

public class SingleValue implements IParameterValidator {
 public void validate(String name, String value) throws ParameterException {
    String[] values = value.split(" ");
    if (values.length > 1) 
    {
      throw new ParameterException("Parameter " + name + " should hold no more than one value, (found " + value +")");
    }
  }
}

So then your variable declaration would look like:

@Parameter(names = "user", description = "the User", validateWidth = SingleValue.class)
private String user;

That should then throw an exception when "--user hugo david --password secret" is passed, but not when "--user hugo --password secret" is passed

Fallso
  • 1,311
  • 1
  • 9
  • 18