Skip to content

Setter is called twice unnecessarily when using defaultValue = Option.NULL_VALUE #2521

Description

@d3cryptofc

EDIT: I ended up preferring not to annotate setters and instead apply my function in the call().

In summary

Using version 4.7.7

  1. I have an optional command flag --input that will have a default value, but it should change according to the operating system, therefore it's dynamic.

  2. Because it's dynamic, I obtain the value through a function call that detects the operating system and returns the data I want, as well as displaying logs.

  3. But if the user enters a value in the flag, the default value is not used, so it's excessive to invoke this function every time unnecessarily, even if the value isn't used.

  4. Therefore, I preferred to annotate methods as setters, validate them, and modify the value right there when necessary:

private File inputFile;

@Option(
    names = {"-i", "--input"},
    paramLabel = "<file>",
    description = "..."
     // NOTE: This ensures the custom setter is always called. It is not redundant.
    defaultValue = Option.NULL_VALUE
)
public void setInputFile(File file) {
    System.out.println("setter called!");
    this.inputFile = ensureDefaultFile(file);
}

/*
$ mycmd app.jar
setter called! (null)
setter called! (null)

$ mycmd --input /any/thing
setter called! (null)
setter called! '/any/thing'
*/
  1. By using defaultValue = Option.NULL_VALUE, it will call my setter even when the user doesn't enter any data, and that's great, it's expected.

  2. The problem is that even when a value is passed to the flag, it still calls the setter to set it to null first, which ends up invoking the function twice in the process. It's as if internally it were doing:

/* This: */
if(option.defaultValue.equals(Option.NULL_VALUE)){
    option.setter(null);
}
setter(arg);

/* Instead of this: */
if(option.defaultValue.equals(Option.NULL_VALUE) && arg == null){
  option.setter(null);
}
else {
  setter(arg);
}

I wonder if I'm going in the right direction. I don't know if there's a better way to do this the way I hope to.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions