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?
Advertisement
Answer
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 {} }