ddso
ddso

Reputation: 1731

Guice: Forcing a binding to be injected as a provider

I'm looking for a way to force certain Guice bindings to be injected as providers only. For example, when there is a configuration like

interface ResultLogger {
    void log(String resultAsString);
}

class ResultLoggerProvider implements Provider<ResultLogger> {
    // ...
}

class ResultDisplayModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(ResultLogger.class).toProvider(ResultLoggerProvider.class);
    }
}

I would like to have way to configure my module so that a class like

@Singleton
class ResultParser {
    private final Provider<ResultLogger> loggerProvider;

    @Inject
    public ResultParser(Provider<ResultLogger> loggerProvider) {
        this.loggerProvider = loggerProvider;
    }
}

can be injected just fine, but an implementation like

@Singleton
class ResultParser {
    private final ResultLogger resultLogger;

    @Inject
    public ResultParser(ResultLogger resultLogger) {
        this.resultLogger = resultLogger;
    }
}

should throw a RuntimeException which notifies the developer that ResultLogger is only available via a provider. The exception would ideally be thrown as soon as possible, e.g. during construction of the injector. I'm looking for an easy way to achieve this using the existing API in Guice 3.0.

Upvotes: 3

Views: 2447

Answers (3)

Geoff Reedy
Geoff Reedy

Reputation: 36011

It should work to bind Provider instead of ResultLogger. That is in your module

bind(new TypeLiteral<Provider<ResultLogger>>(){}).to(ResultLoggerProvider.class);

Upvotes: -1

Stan Kurilin
Stan Kurilin

Reputation: 15792

I think that it isn't right way. I guess you need smt like

interface ResultLogger {
    void log(String resultAsString);
}
class ResultLoggerWrapper implements ResultLogger {
      @Inject @Named("day") ResultLogger dayLogger;
      @Inject @Named("night") ResultLogger nightLogger;
      public void log(String resultAsString){
           if(isDay()) {
                 dayLogger.log(resultAsString)
           } else {
                 nightLogger.log(resultAsString)
           }
      }
}  

bind(ResultLogger.class).to(ResultLoggerWrapper.class);

Upvotes: 1

M.L.
M.L.

Reputation: 4706

Maybe you should not implement Provider at all and just have a

@Singleton
public class ResultLoggerProvider {
   public ResultLogger get() {...}
   // ...
}

@Singleton
class ResultParser {
   private final ResultLoggerProvider loggerProvider;

   @Inject
   public ResultParser(ResultLoggerProvider loggerProvider) {
      this.loggerProvider = loggerProvider;
   }
}

and remove the other bindings.

Upvotes: 4

Related Questions