Domanda

I am trying to use Guice 3.0 AssistedInject, and it won't instantiate the factory.

SSCCE Code:

Parent class

public class ParentClass() {
  @Inject private MyFactory myFactory;
  private final Foo foo;
  private final Bar bar;
  public ParentClass() {
    if(myFactory == null) System.err.println("Error: I should have injected by now!");
    foo = myFactory.create(new Map<String, Object>());
    // etc.
  }
}

Factory Interface

public interface MyFactory {
  Foo create(Map<String, Object> mapA);
  Bar create(Map<String, Object> mapB, Map<String, Object> mapC);
}

Module

public class ParentModule extends AbstractModule {
  @Override
  protected void configure() {
    install(new FactoryModuleBuilder()
        .implement(Foo.class, FooImpl.class)
        .implement(Bar.class, BarImpl.class)
        .build(MyFactory.class));
  }

FooImpl

public class FooImpl implements Foo {
  private final Map<String, Object> mapA;
  @AssistedInject
  public FooImpl(@Assisted Map<String, Object> mapA) {
    this.mapA = mapA;
  }
}

BarImpl is very similar to FooImpl. What is going wrong here? Note also that I tried both @AssistedInject and @Inject here, both cause the error.

Output:

Error: I should have injected by now!
Exception in thread "main" com.google.inject.ProvisionException: Guice provision errors:

1) Error injecting constructor, java.lang.NullPointerException
  at ParentClass.<init>(ParentClass.java:7)
  while locating com.my.package.ParentClass

1 error
        at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
        at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
        at com.my.package.ParentMain.main(ParentMain.java:16)
Caused by: java.lang.NullPointerException
        at com.my.package.ParentClass.<init>(ParentClass.java:9)
        at com.my.package.ParentClass$$FastClassByGuice$$d4b3063a.newInstance(<generated>)
        at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
        ... 8 more

Note that line 9 is the line of the first call to myFactory.create()

È stato utile?

Soluzione

According to Guice's javadoc, field injection is performed after constructor injection.

I assume your ParentClass instance is created by Guice. When your ParentClass's constructor is executed, its myFactory field has not been injected yet.

Altri suggerimenti

Two things. To use an injection in a constructor, you must use a constructor injection:

public class ParentClass {

    private final Foo foo;
    private final Bar bar;

    @Inject
    public ParentClass(MyFactory myFactory) {
        if(myFactory == null) System.err.println("Error: I should have injected by now!");
        this.foo = myFactory.create(new HashMap<String, Object>());
        this.bar = myFactory.create(new HashMap<String, Object>(), new HashMap<String, Object>());
    }
}

Also, since your factory has two parameters of the same type, you need to name them:

public interface MyFactory {
    Foo create(Map<String, Object> mapA);
    Bar create(@Assisted("B") Map<String, Object> mapB, @Assisted("C") Map<String, Object> mapC);
}

and

public class BarImpl implements Bar {

    private final Map<String, Object> mapA;
    private final Map<String, Object> mapB;

    @AssistedInject
    public BarImpl(@Assisted("B") Map<String, Object> mapA, @Assisted("C")  Map<String, Object> mapB) {
        this.mapA = mapA;
        this.mapB =mapB;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top