tags:

views:

244

answers:

2

Here is the problem I met:

Class SimpleCommand implements Executable{
private final ConfigManager config;
private String name;

@Inject    
public SimpleCommand(ConfigManager config, @Assisted String name){
  this.config = config;
  this.name = name;
  }
}

Class MyModule extends AbstractModule{
@Override
protected void configure() {
     bind(CommandFactory.class).toProvider(FactoryProvider.newFactory(CommandFactory.class, SimpleCommand.class));
     bind(Executable.class).to(SimpleCommand.class);
     }
}

When I try to get instance of SimpleCommand using:

Guice.createInjector(new MyModule()).getInstance(CommandFactory.class).create("sample command");

I got this error:

1) No implementation for java.lang.String annotated with @com.google.inject.assistedinject.Assisted(value=) was bound.
  while locating java.lang.String annotated with @com.google.inject.assistedinject.Assisted(value=)
    for parameter 2 at model.Command.<init>(SimpleCommand.java:58)
  at module.MyModule.configure(MyModule.java:34)

So my problem is how can I bind SimpleCommand to Executable when SimpleCommand has Assisted Injected parameter?

Here is the CommandFactory and its implementation:

public interface CommandFactory{
  public Command create(String name);
}


public class GuiceCommandFactory implements CommandFactory{
  private Provider<ConfigManager> configManager ;

  @Inject
  public GuiceCommandFactory(Provider<ConfigManager> configManager){
    this.configManager = configManager;
  }

  public Command create(String cmd){
    return new Command(configManager.get(), cmd);
  }
}
A: 

Hmm... code looks good. Can you include the factory interface?

Jesse Wilson
@Jesse, I've uploaded the CommandFactory.
eric2323223
A: 

There seem to be two problems.

One is with bind(Executable.class).to(SimpleCommand.class). Binding Executable to SimpleCommand implies that a SimpleCommand can be injected directly to classes with a dependency on Executable. But since Guice cannot create an instance of SimpleCommand itself (it needs the assisted parameter provided to the factory), the bind is invalid. The error message is treating @Assisted as a normal binding annotation, and trying to resolve a String bound to it in the constructor, but none is bound.

Beyond that, it seems like if you're using Assisted Inject to create a factory for Executables, you can't create another binding to it without using some binding annotation on it. Since you're using assisted inject, presumably you want to create multiple instances of Executable using your factory, so any individual Executable you wanted to bind directly would probably have some specific meaning in your system, right?

In that case, you should just use some binding annotation like @Default and a provider method like so:

@Provides
@Default
protected Executable provideDefaultExecutable(ConfigManager configManager) {
   return new SimpleCommand(configManager, "My default command");
}
ColinD