1

I have recently upgraded my project to Picocli 4.2.0, including the removal of all deprecated method calls, and I have been continuing the work I described here. I'm running into the same problem again -- I have a field that doesn't seem to reset. The only thing that's different about this from my other question is that now the field is a collection. The code looks like this:

@Command(name="watch", description="Alters the set of watched productions", subcommands={HelpCommand.class})
static public class Watch implements Runnable
{
    @ParentCommand
    ProductionC parent; // injected by picocli

    @Option(names={"on", "-e", "--on", "--enable"}, description="Enables watching of given productions")
    List<String> productionsToEnable;

    @Option(names={"off", "-d", "--off", "--disable"}, description="Disables watching of given productions")
    List<String> productionsToDisable;

    @Override
    public void run()
    { ... }

(Full code available here.)

Specifically, the productionsToEnable does not seem to reset. The way the call is being made is part of a unit test:

@Test
public void testCanListTracedRules() throws Exception
{
    loadRules();
    agent.getInterpreter().eval("production watch --on b");
    agent.getInterpreter().eval("production watch --on c");

    final StringWriter result = new StringWriter();
    agent.getPrinter().pushWriter(result);
    agent.getInterpreter().eval("production watch");
    agent.getPrinter().popWriter();
    assertEquals("b\nc", result.toString());
}

(Full code available here.)

The string "c" from the last call to production watch is still present in productionsToEnable when the production watch command is called in the last eval.

Note that the code links above are on the jsoar-command-performance branch in case it's helpful to get a closer look.

marinier
  • 387
  • 3
  • 13

1 Answers1

0

There is a regression in picocli 4.2.0 that means that @Option-annotated fields in subcommands are not reset to their initial value when a CommandLine instance is reused.

This issue is tracked in the picocli project issue tracker in this ticket. (Status 2020-04-20: fixed in master.)

Scope

With picocli 4.2.0, subcommand options are not cleared between invocations. This impacts applications that reuse a CommandLine instance in multiple invocations. If an option was specified in the first invocation and omitted in the second invocation, it will incorrectly retain the value from the first invocation.

The problem does not manifest when a subcommand is invoked only once in a JVM process. Also, applications that do not reuse a CommandLine instance, and applications without subcommands, are not impacted.

The problem was introduced in version 4.2.0 and does not exist in picocli 4.1.4 and earlier.

Workaround

This regression does not apply to options that have a defaultValue defined in the annotation: options defined as @Option(... defaultValue="...") will correctly be reset to the default value in between multiple invocations. Use the defaultValue annotation where possible.

Cause

The cause is related to recent changes for lazy subcommand instantiation and repeatable subcommands.

The ticket on the picocli issue tracker has more details and progress updates.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • I actually thought of using a default value, but in my case the option is a `List`. What is the proper way to provide a default for that? (I would just want an empty list.) – marinier Apr 13 '20 at 23:18
  • Away from PC now, but I believe `defaultValue = ""` would work. – Remko Popma Apr 13 '20 at 23:30
  • Ok I'll give it a try. What if I actually want it to be null? (I'm not sure it's necessary for this specific case, but there are other commands that expect a null String, for example). – marinier Apr 13 '20 at 23:31
  • For `null` default values, one way would be to configure a [custom default provider](https://picocli.info/#_default_provider), but perhaps downgrading to picocli 4.1.4 is simpler. – Remko Popma Apr 13 '20 at 23:34
  • I downgraded to 4.1.4 and that seems to be working great! If this is expected to be fixed in 4.3, I'd rather just wait for that rather than trying to workaround it and then taking the workaround out later. – marinier Apr 14 '20 at 17:38
  • Status update: [fixed in master](https://github.com/remkop/picocli/issues/990). The ticket shows steps to verify if the proposed solution actually solves your problem. Feedback welcome! – Remko Popma Apr 20 '20 at 02:20
  • Thank you for the confirmation! – Remko Popma Apr 20 '20 at 19:17