Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting "classes must have either one (and only one) constructor" error?

I have been trying to get Guice working but end up with this:

Classes must have either one (and only one) constructor

My interface:

public interface AddrBookStore {
    public Contact getContactByKey(String key);
    public void addContact(Contact c);
}

The implementation:

public class RdbmsBasedAddrBookStore implements AddrBookStore {
    private Connection connection;

    public RdbmsBasedAddrBookStore(Connection connection) {
        this.connection = connection;
    }

    @Override
    public Contact getContactByKey(String key) throws AddrBookException
    {} 
    @Override
    public void addContact(Contact c) throws AddrBookException
    {}
}

The binding module:

public class ABguiceConfingModule extends AbstractModule {
    @Override
    protected void configure() {        
        bind(AddrBookStore.class).to(RdbmsBasedAddrBookStore.class);
    }
}

The AddrBook client where I am injecting:

public class AddrBook {
    private AddrBookStore store;

    @Inject
    public AddrBook(AddrBookStore store)
    {
        this.store = store;
    }
    ... other methods;
}

And my main:

public class App 
{
    public static void main( String[] args ) throws Exception
    {
        Injector injector = Guice.createInjector(new ABguiceConfingModule() );
        AddrBookStore store = injector.getInstance( AddrBookStore.class );

        AddrBook book = new AddrBook(store);
        AddrBookCLI cli = new AddrBookCLI(book);
        cli.interact(new InputStreamReader(System.in), new OutputStreamWriter(System.out));

}}

After all this, I'm getting this error:

1) Could not find a suitable constructor in addrbook.store.RdbmsBasedAddrBookStore. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
[ERROR] at addrbook.store.RdbmsBasedAddrBookStore.class(RdbmsBasedAddrBookStore.java:23)
[ERROR] at addrbook.ABguiceConfingModule.configure(ABguiceConfingModule.java:13)

I have experience with Spring and not with Guice. Where am I going wrong here?

like image 207
Kartz Kartel Avatar asked Jun 28 '16 18:06

Kartz Kartel


1 Answers

You haven't set up the primary dependency for AddrBookStore. You need to have a binding for Connection, and then you need to annotate the constructor with @Inject.

You've set up the AddrBookStore class but clearly it's wrapping an Rdbms... except you haven't set up the Rdbms.

There are lots of ways to do this in Guice, in this case I would probably do it with a Provider<Connection>, that way you have an entire class to put the code for spinning up your connection to the database, so something like:

public class ConnectionProvider implements Provider<Connection> {
    public Connection get() {
        // put your code that connects to the database here
    }
}

Then your module would be:

public class ABguiceConfingModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AddrBookStore.class).to(RdbmsBasedAddrBookStore.class);
        bind(Connection.class).toProvider(ConnectionProvider.class);
    }
}

And then finally your AddrBookStore:

public class RdbmsBasedAddrBookStore implements AddrBookStore {
    private Connection connection;

    @Inject
    public RdbmsBasedAddrBookStore(Connection connection) {
        this.connection = connection;
    }

    @Override
    public Contact getContactByKey(String key) throws AddrBookException
    {}

    @Override
    public void addContact(Contact c) throws AddrBookException
    {}
}
like image 118
durron597 Avatar answered Nov 15 '22 01:11

durron597