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

Custom Factory fails to create collection for @Options #784

Closed
bobtiernay-okta opened this issue Aug 14, 2019 · 3 comments
Closed

Custom Factory fails to create collection for @Options #784

bobtiernay-okta opened this issue Aug 14, 2019 · 3 comments
Labels
theme: compatibility Issues related to binary and source backwards compatibility type: doc 📘
Milestone

Comments

@bobtiernay-okta
Copy link
Contributor

Right now, for the following command method option:

@Option(names = "--fields", description = "The fields to display", defaultValue = "timestamp,thread,level,className,message,attributes", split = ",", showDefaultValue = ALWAYS) Set<LineField> fields,

I'm getting the following exception:

INVALID: picocli.CommandLine$ParameterException: ConfigurationException: Guice configuration errors:

1) No implementation for java.util.Set was bound.
  while locating java.util.Set

1 error while processing argument at or before arg[1] 'logs' in [monolith, logs]: com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for java.util.Set was bound.
  while locating java.util.Set

1 error
	at picocli.CommandLine$ParameterException.create(CommandLine.java:14971)
	at picocli.CommandLine$ParameterException.access$16700(CommandLine.java:14895)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:11003)
	at picocli.CommandLine$Interpreter.processArguments(CommandLine.java:11129)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:10997)
	at picocli.CommandLine$Interpreter.processArguments(CommandLine.java:11129)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:10997)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:10888)
	at picocli.CommandLine.parseArgs(CommandLine.java:1271)
	at cli.runtime.Runner.execute(Runner.java:62)
	at cli.runtime.Runner.run(Runner.java:57)
	at cli.Main.main(Main.java:17)
Caused by: com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for java.util.Set was bound.
  while locating java.util.Set

1 error
	at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1075)
	at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1034)
	at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1086)
	at cli.runtime.Factory.create(Factory.java:39)
	at picocli.CommandLine$Interpreter.createCollection(CommandLine.java:11950)
	at picocli.CommandLine$Interpreter.applyValuesToCollectionField(CommandLine.java:11709)
	at picocli.CommandLine$Interpreter.applyOption(CommandLine.java:11383)
	at picocli.CommandLine$Interpreter.applyDefault(CommandLine.java:11073)
	at picocli.CommandLine$Interpreter.applyDefaultValues(CommandLine.java:11042)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:10996)
	... 9 more

My Factory is pretty simple, which simply delegates to Guice. But since I don't have a component created for options, it fails. This behavior seems to have changed between 3.x and 4.x, but I'm not sure how to resolve for command methods. I was able to fix it for fields by supplying a default field value.

@remkop
Copy link
Owner

remkop commented Aug 14, 2019

You are right.

The recommended way to fix this is to delegate to the picocli default factory if the requested bean cannot be found in the configuration. This is what the built-in PicocliSpringFactory does.

Something like this:

    @Override
    public <K> K create(Class<K> clazz) throws Exception {
        try {
            return getBeanOrCreate(clazz); // ask the dependency injection container
        } catch (Exception e) {
            return CommandLine.defaultFactory().create(clazz); // fallback if missing
        }
    }

I tried to track down when the change was made to delegate the creation of Collections to the factory. I believe you are right that this happened around 4.0. There is no separate ticket for this and it was not mentioned in the release notes. It should have been mentioned under potential breaking changes.

I am thinking to update the 4.0 release notes to add this to the list of breaking changes.

I will also update the Guice example to add a try/catch and fall back to the picocli default factory as in the above example.

@remkop remkop added this to the 4.0.3 milestone Aug 14, 2019
@bobtiernay-okta
Copy link
Contributor Author

That works, thanks a lot!

@remkop remkop added the theme: compatibility Issues related to binary and source backwards compatibility label Aug 15, 2019
remkop added a commit that referenced this issue Aug 16, 2019
… should fall back to the default factory to enable the creation of collections for `@Option`-annotated methods and fields.
@remkop
Copy link
Owner

remkop commented Aug 16, 2019

User manual updated, and added entry to the 4.0 release notes under breaking changes.
Thanks for pointing this out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: compatibility Issues related to binary and source backwards compatibility type: doc 📘
Projects
None yet
Development

No branches or pull requests

2 participants