Search code examples
javadependency-injectionguicefactory

Passing constructors for outer dependency into Guice implementation


I have a Job, which should read data from deep storage. I am using Guice DI for my project.

There is a deep store already written and coming as an outer dependencie. I am struggling with instantiating the client in Guice

Here is the code

JobModule

public class JobModule extends AbstractModule {
  private Config config;

  JobModule(Config config) {
     this.config = config;
  }

  @Override
  protected void configure() {
    bind(Reader.class).to(DeepStoreReader.class);
  }

  @Provides
  @Named("config")
  Config provideConfig() {
    return this.config;
  }
}

Reader Interface

public interface Reader {
  List<String> getData(String path);
}

DeepStoreReader

public class DeepStoreReader implements Reader {
  private final DeepStoreClient deepStoreClient;

  DeepStoreReader(@Named("config") Config config) {
     this.deepStoreClient = new DeepStoreClient(config);
  }

  @Override
  public List<String> getData(String path) {
    return this.deepStoreClient.getData(path);
  }
}

The issue is I don't want to instantiate DeepStoreClient inside the DeepStoreReader constructor, because it becomes difficult to test DeepStoreReader, since I won't be able to mock DeepStoreClient

What is the preferred way to instantiate a client in such cases? DeepStoreClient is not a Guice module/implementation and is coming as an outer published dependency

PS: I am new to DI and learning Guice


Solution

  • What you want is constructor injection, e.g.:

    @Inject
    public DeepStoreReader(DeepStoreClient deepStoreClient) {
        this.deepStoreClient = deepStoreClient;
    }
    

    Guice will take care of instantiating the DeepStoreClient for you.

    EDIT:

    If DeepStoreClient itself has dependencies, you can also annotate that constructor:

    @Inject
    public DeepStoreClient(@Named("config") Config config) {
        // ... 8< ...
    }