Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default value should not be validated for required parameter #566

Closed
gwenn opened this issue Aug 26, 2023 · 4 comments · Fixed by #567
Closed

Default value should not be validated for required parameter #566

gwenn opened this issue Aug 26, 2023 · 4 comments · Fixed by #567

Comments

@gwenn
Copy link
Contributor

gwenn commented Aug 26, 2023

Minimal example:

import com.beust.jcommander.IValueValidator;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;

public class JC {
	@Parameter(names = "-shift", required = true, validateValueWith = StrictlyPositiveInteger.class)
	private int shift = 1; // FIXME: we must not need to specify a default value compatible with StrictlyPositiveInteger when required is true

	public static void main(String[] args) {
		JCommander.newBuilder()
			.addObject(new JC())
			.build()
			.parse(args);
	}

	public static class StrictlyPositiveInteger implements IValueValidator<Integer> {
		@Override
		public void validate(String name, Integer i) throws ParameterException {
			if (i <= 0) {
				throw new ParameterException("Parameter " + name
					+ " should be strictly positive (found " + i + ")");
			}
		}
	}
}

If we remove the default meaningless (because parameter is required) value of shift (private int shift;), JCommander throws:

Exception in thread "main" com.beust.jcommander.ParameterException: Parameter -shift should be strictly positive (found 0)
	at JC$StrictlyPositiveInteger.validate(JC.java:21)
	at JC$StrictlyPositiveInteger.validate(JC.java:17)
	at com.beust.jcommander.ParameterDescription.validateValueParameter(ParameterDescription.java:364)
	at com.beust.jcommander.ParameterDescription.validateValueParameter(ParameterDescription.java:353)
	at com.beust.jcommander.ParameterDescription.validateDefaultValues(ParameterDescription.java:164)
	at com.beust.jcommander.ParameterDescription.init(ParameterDescription.java:157)
	at com.beust.jcommander.ParameterDescription.<init>(ParameterDescription.java:65)
	at com.beust.jcommander.JCommander.addDescription(JCommander.java:631)
	at com.beust.jcommander.JCommander.createDescriptions(JCommander.java:601)
	at com.beust.jcommander.JCommander.parse(JCommander.java:361)
	at com.beust.jcommander.JCommander.parse(JCommander.java:342)
	at JC.main(JC.java:14)

See

//
// Validate default values, if any and if applicable
//
if (defaultObject != null) {
if (parameterAnnotation != null) {
validateDefaultValues(parameterAnnotation.names());
}
}

@mkarg
Copy link
Collaborator

mkarg commented Aug 28, 2023

@cbeust Chime in if needed, but I personally do neither see that this is a bug nor that it could get solved. The reproducer deliberately is using int instead of Integer, so the default is 0, not null. Hence defaultObject is not null, but an Integer instance holding the value 0. Hence it is correct that JCommander applies the validator.

@gwenn There is an implied default provided by the Java language itself, even if the application programmer does not explicitly provide a default value (try to find out whether there is no default or whether the default is 0 for an int variable in Java, then you will understand this explanation). There is a simple workaround: Replace int by Integer and your code will work just fine. That's why Integer exists in Java, as it allows to tell between the value 0 and "having no value" (null). JCommander cannot and will not change the way Java deals with defaults.

@gwenn
Copy link
Contributor Author

gwenn commented Aug 28, 2023

@mkarg But for a required parameter, using a non-nullable type (int instead of Integer) seems wise, no ?
And I don't want to change java defaults, I want JCommander to ignore any default value for required parameter because default value is meaningless for required parameter.

@mkarg
Copy link
Collaborator

mkarg commented Aug 28, 2023

@gwenn I do not see why int should be more wise than Integer, actually: You could instantly workaround your problem that way, which is very wise. ;-) Implementing the requested change just for required values is acceptable on the other hand. Feel free to post a PR, I would be happy to review it. :-)

@gwenn
Copy link
Contributor Author

gwenn commented Aug 28, 2023

@mkarg see #567 (I am not sure that unit test should be added to the 1500 lines JCommanderTest class)

mkarg pushed a commit that referenced this issue Aug 29, 2023
* Ignore default value for required parameter

Fix #566
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants