I am trying to use guice and I want to create a Singleton of random webservice client in Java Play 2.6
For now I have my WS client and it loads as a java play module. When I run the application, no problem, my client is able to use the java play Configuration (com.typesafe.config.Config
), which is injected. But if I try to use my client anywhere else, I get an error saying No implementation for com.typesafe.config.Config was bound
.
Here is my (very simple) client :
import play.Logger;
import com.typesafe.config.Config;
@Singleton
public class MyClient {
final Config config;
@Inject
public MyClient(Config config) {
this.config = config;
Logger.warn("constructor called")
Logger.warn("Some config param:"+config.getString("some_param"))
}
public void doSomething() {
Logger.warn("doSomething() called")
}
}
My Module implementing Guice's AbstractModule :
import com.google.inject.AbstractModule;
public class MyClientModule extends AbstractModule {
@Override
protected void configure() {
bind(MyClient.class).asEagerSingleton();
}
}
When I tell Play to use it as a module in applicationf.conf
, it works (i get the "Constructor called"
and the "Some config param"
warning logs in the console):
play {
modules {
enabled += external.MyClientModule
}
}
But If I try to call it from my HomeController
:
public class HomeController extends Controller {
public Result index() {
Injector myClientInjector = Guice.createInjector(new MyClientModule());
MyClient myClient = myClientInjector.getInstance(MyClient.class);
return ok(views.html.index.render());
}
}
then I get the following error :
[CreationException: Unable to create injector, see the following errors:
1) No implementation for com.typesafe.config.Config was bound.
while locating com.typesafe.config.Config
for the 1st parameter of external.MyClient.<init>(MyClient.java:121)
at external.MyClientModule.configure(MyClientModule.java:8)
1 error]
I'm pretty sure there are a few things wrong here, so what would be the correct way to bind it and then use it ?
In the HomeController, use constructor injection :
@Inject
public HomeController (final MyClient myclient) {
this.myclient = myclient;
}
You can annotate 1 constructor like this, so it needs to contain all the classes you want to inject. You can combine constructor and field injection, but that is not recommended.