Reputation: 2549
I just started using Guice and Play so I guess this is a long but basic question. I checked the guide here: http://eng.42go.com/play-framework-dependency-injection-guice/ but I don't know why my code fails.
First I have a global injector:
public class GlobalInjector {
private static Injector guiceInjector;
private static List<AbstractModule> modules = new ArrayList<AbstractModule>();
public static Injector getInjector() {
return guiceInjector;
}
public static loadModules() {
guiceInjector = Guice.createInjector(modules);
}
public static addModule(AbstractModule module) {
modules.add(module);
}
}
Also I have added Guice to Play by extending the GlobalSettings
class (also modified application.global)
public class GuiceExtendedSettings extends GlobalSettings {
@Override
public void onStart(Application app) {
GlobalInjector.loadModules();
}
@Override
public <A> A getControllerInstance(Class<A> controllerClass) {
return GlobalInjector.getInjector().getInstance(controllerClass);
}
}
Then I have my test module acting as a plugin in Play (some required methods are omitted as they do nothing in this piece):
public class TestModule extends AbstractModule implements Plugin {
@Override
public void configure() {
// Worker is a simple class
Worker worker = new SimpleWorker();
MapBinder<String, Worker> mapBinder = MapBinder.newMapBinder(binder(), String.class, Worker.class);
mapBinder.addBinding(worker.getName()).toInstance(worker);
}
@Override
public void onStart() {
GlobalInjector.addModule(this);
}
}
Worker
is a simple interface:
public interface Worker {
public String getName();
public String getResult();
}
SimpleWorker
:
public class SimpleWorker implements Worker {
public String getName() {
return "SimpleWorker";
}
public String getResult() {
return "works";
}
}
And here is the code piece showing the controller logic: nothing but just print all worker results in the map injected
public class TestController extends Controller {
@Inject
Map<String, Worker> workers;
public Result showWorkers() {
StringBuilder sb = new StringBuilder();
for (Worker worker : workers) {
sb.append(worker.getName() + ": " + worker.getResult() + "</br>");
}
return ok(sb.toString()).as("text/html");
}
}
OK. To make this work, I put the following line in play.plugins:
100:test.TestModule
My idea is: Play loads the plugin (TestModule) -> TestModule adds itself to the GlobalInjector -> GlobalInjector creates Guice injector -> Guice injects the map to the controller
However the result was
Guice didn't inject the map. The map is still null
.
Also how should I test it? (i.e. how can I inject different workers to that map? I hard-coded that part in the above code. But I'm looking for a dynamic way by using different modules.)
public class Test {
@Test
public void testInjector() {
running(fakeApplication(), new Runnable() {
public void run() {
// how can I inject using different modules here?
}
});
}
}
Upvotes: 0
Views: 1273
Reputation: 21
You need to use the fakeApplication helper method that allows you to specify both your global settings object and additional plugins. See http://www.playframework.com/documentation/api/2.1.x/java/play/test/Helpers.html#fakeApplication(java.util.Map,%20java.util.List,%20play.GlobalSettings) for more information.
But basically, your test should look something like:
public class Test {
@Test
public void testInjector() {
Map<String, Object> config = new HashMap<String, Object>();
// add any additional config options, e.g. in-memory db
List<String> plugins = new ArrayList<String>();
plugins.add("full.package.name.TestModule");
GlobalSettings global = null;
try {
global = (GlobalSettings) Class.forName("full.package.name.GuiceExtendedSettings").newInstance();
} catch(Exception e) {}
running(fakeApplication(config, plugins, global), new Runnable() {
public void run() {
// do some assertions
}
});
}
}
You also need to make sure that guice instantiates the test controller or the workers map won't be injected.
Upvotes: 1