No implementation was bound - Java Guice

Lorena Nicole picture Lorena Nicole · Jul 15, 2014 · Viewed 56.3k times · Source

Novice here trying to use a dummy Java Facebook app that uses Guice to inject a database dependency into the Facebook factory but continue to have Guice error out telling me:

### No implementation for com.example.storage.Db annotated with @com.example.storage.annotations.SystemDb() was bound while locating com.example.storage.Db annotated with @com.example.storage.annotations.SystemDb() for parameter 0 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb at com.example.facebook.client.guice.FacebookClientModule.configure

### Could not find a suitable constructor in com.example.facebook.statsd.StatsdClient. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private. at com.example.facebook.statsd.StatsdClient.class while locating com.example.facebook.statsd.StatsdClient for parameter 1 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb. com.example.facebook.client.guice.FacebookClientModule.configure

Code for app:

app.java

package com.example.facebook;

import com.google.inject.Guice;
import com.restfb.Connection;
import com.restfb.types.Post;
import com.example.facebook.client.FacebookClientFactory;
import com.example.facebook.client.RobustFacebookClient;
import com.example.facebook.client.guice.FacebookClientModule;
import com.example.facebook.statsd.StatsdClient;

public class App  {
    public static void main ( String[] args ) {
          final FacebookClientFactory facebookClientFactory =
            Guice.createInjector(new FacebookClientModule()).getInstance(FacebookClientFactory.class);
          //error from line above
          final RobustFacebookClient robustFacebookClient =
            facebookClientFactory.create("accessToken");
          //more ...
    }

The resulting error points me to the FacebookClientModule binding:

FacebookClientModule.java

public class FacebookClientModule extends AbstractModule {
    bind(FacebookExceptionHandler.class).to(FacebookExceptionHandlerDb.class);
    //error resulting from the failed binding on the FacebookExceptionHandlerDB class

    install(new FactoryModuleBuilder()
            .implement(FacebookClient.class, RobustFacebookClient.class)
            .build(FacebookClientFactory.class));
    }

}

Where inside the FacebookExceptionHandleDB class the constructor has the injection:

FacebookExceptionHandlerDB.java

public class FacebookExceptionHandlerDb implements FacebookExceptionHandler {

    // list of class String variables ... 
    private final FacebookErrorParser parser;
    private final Db db;
    private StatsdClient statsd;

    @Inject
    public FacebookExceptionHandlerDb(@SystemDb Db db, StatsdClient statsd,    FacebookErrorParser parser) {
        this.db = db;
        this.statsd = statsd;
        this.parser = parser;
    }
}

From what I can gleam, the dependency injection for parameters zero and one, db and statsD respectively, is failing. Could someone point out where or what in the app code is missing?

Answer

Miguel Lavigne picture Miguel Lavigne · Jul 15, 2014

At first glance it seems like your missing the bindings for the Db annotated dependency and the StatsdClient.

You'll need to provide the missing bindings to your module like so

bind(Db.class).annotatedWith(SystemDb.class).to(DbImplOfSomeSort.class);
bind(StatsdClient.class).to(StatsdClientImplOfSomeSort.class);

Guice is able to automatically inject Concrete Class with either a public no argument constructor or a constructor with @Inject without any specific defined binding in your module but when it comes to Interfaces you have to define the necessary bindings.

Here Db.class and StatsdClient.class are interfaces which you need to bind to specific implementation.