I am a guice newbie trying to figure out how to implement assisted inject in the guice using FactoryModuleBuilder. I consulted the guice java docs for implementing FactoryModuleBuilder.
I have done everything exactly as it says in the docs. Its not injecting the factory. I referred to this stack overflow question :Guice AssistedInject won't inject the factory which had the same problem. It talks about the field injection before constructor injection problem. I followed it and I am trying to call the Parent class using a caller class but I am still getting the null pointer exception. What is going wrong here?
Caller class
public class MAIN {
@Inject private static MyFactory factory;
public static void main(String[] args){
ParentClass newbie = new ParentClass(factory);
}
}
I am still getting the exception:
Exception in thread "main" java.lang.NullPointerException
at com.pkg.ParentClass.<init>(ParentClass.java:19)
at com.pkg.MAIN.main(MAIN.java:10)
Parent Class
public class ParentClass {
private final Foo test;
@Inject
public ParentClass(MyFactory factory){
test = factory.create(new HashMap<String,Object>());
}
}
Module Implementation: ParentModule
public class ParentModule extends AbstractModule{
@Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Foo.class, FooImpl.class)
.build(MyFactory.class));
}
}
Factory Interface: MyFactory
public interface MyFactory {
Foo create(Map<String,Object> map);
}
Class Interface : Foo
public interface Foo{
}
Class:FooImpl
public class FooImpl implements Foo {
private final Map<String,Object> mapA;
@AssistedInject
public FooImpl(@Assisted Map<String,Object> map){
mapA=map;
}
}
You have two problems here.
First and most important, you are not creating Injector
anywhere. Obviously, without an injector nothing will work. You have to create an injector instance using your module:
Injector injector = Guice.createInjector(new ParentModule());
Your second problem is that you want to inject your factory into a static field:
@Inject private static MyFactory factory;
Although Guice can work with static fields if you tell it explicitly, it is considered very bad practice. You should never inject into static fields unless you are working with some legacy code.
What you really want is something like this:
public class Main {
@Inject
private MyFactory factory;
public void run() {
ParentClass newbie = new ParentClass(factory);
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ParentModule());
Main main = injector.getInstance(Main.class);
main.run();
}
}
Note that program entry point (main
) is now creates an injector and then uses it to create an instance of Main
class, which will have its field injected automatically. And then it calls method run()
on the instance which performs actual work.
Note, however, that this is all really valid only for illustrative purposes for assisted injection. You should not structure your real code like this. For example, you're using new
operator to create classes whose constructors are annotated with @Inject
. Don't ever do this! If you mark some class (i.e. its constructors or fields) as @Inject
able, then this class should be used only by the means of injection. Your Main
code can be shortened to the following:
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ParentModule());
ParentClass newbie = injector.getInstance(ParentClass.class);
}
}
Here newbie
will automatically receive an instance of MyFactory
into its constructor since it is annotated with @Inject
.
And I already wrote about statics.