0
votes

all

I have some questions regarding Google Guice. Any help is appreciated.

I have a handler interface and an implementation of it.

public interface Handler {
   void handle();
}
public class HandlerImpl implements Handler {
   private Filter filterOne;

   @Override
   void handler() {
     filterOne.foo();
   }
}

Filter is another interface:

public interface Filter {
   void foo();
}

There are multiple implementation of it.

public class FilterOne implements Filter {
   void foo() {
   }
}

public class FilterTwo implements Filter {
   void foo() {
   }
}

Then in my Guice module:

public class HandlerModule extends AbstractModel {

  @Override
  protected void configure() {
     bind(Handler.class).to(HandlerImpl.class);
  }

  @Provides
  @Singleton
  public Handler provideHandler(@Named("filterOne")filter filterOne) {
    return new HandlerImpl(filterOne);
  }

  @Provides
  @Singleton
  @Named("filterOne")
  public Filter provideFilterOne() {
    return new FilterOne();
  }

  @Provides
  @Singleton
  @Named("filterTwo")
  public Filter provideFilterTwo() {
    return new FilterTwo();
  }
}

With above implementation, I'm always getting the error - Could not find a suitable constructor in HandlerImpl. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.

I'm using @Named to differ two filters. Am I using it wrong? Is it because I have two implementations of Filter and the Guice cannot tell which one to use when try to provide the HandlerImpl?

1
"Is it because I have two implementations of Filter and the Guice cannot tell which one to use when try to provide the HandlerImpl?" Exactly. So which one do you want to use? Or how do you want to decide which one to use? - Olivier Grégoire
I updated the question. For each filter, I have a @Named annotation. Then in the handler, I use that to represent which filter factory I want to use. Am I using it a wrong way? - Jasonsfk

1 Answers

1
votes

You are binding Handler.class twice:

  • In configure() method: bind(Handler.class).to(HandlerImpl.class);
  • As a provider:
  @Singleton
  public Handler provideHandler(@Named("filterOne")filter filterOne) {
    return new HandlerImpl(filterOne);
  }

The first of these bindings can't work, since HandlerImpl doesn't have a constructor annotated with @Inject. If you fix it though, it still won't work - you can't provide multiple bindings for the same key.

TL;DR: remove the bind(Handler.class).to(HandlerImpl.class); from the configure() method