Custom provider should not be used when its fields were not injected correctly
- Dominant language
- Java
- Stars
- 12.7k
- Forks
- 1.7k
- Avg merge
- 11m
- Merged PRs (30d)
- 2
Description
I have a custom provider, which needs an `@Injected` field. When the injection of this fields fails due to exception being thrown, the provider's `get()` method should not be called, as referencing the field results in `NullPointerException`.
The result is very misleading and log polluting (see also #676 and #728) provisioning errors:
```
1) Error in custom provider, java.lang.NullPointerException
at guice.NPEInjectionTest$1.configure(NPEInjectionTest.java:26)
while locating guice.NPEInjectionTest$B
for field at guice.NPEInjectionTest$2$1.b(NPEInjectionTest.java:1)
at guice.NPEInjectionTest$2.configure(NPEInjectionTest.java:37)
Caused by: java.lang.NullPointerException
at guice.NPEInjectionTest$1$1.get(NPEInjectionTest.java:30)
at guice.NPEInjectionTest$1$1.get(NPEInjectionTest.java:1)
at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
at com.google.inject.internal.InternalFactoryToInitializableAdapter.provision(InternalFactoryToInitializableAdapter.java:53)
at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)
at com.google.inject.internal.InternalFactoryToInitializableAdapter.get(InternalFactoryToInitializableAdapter.java:45)
at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54)
at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:93)
at com.google.inject.internal.MembersInjectorImpl$1.call(MembersInjectorImpl.java:80)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1085)
at com.google.inject.internal.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:80)
at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:223)
at com.google.inject.internal.Initializer.injectAll(Initializer.java:132)
at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:174)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
at com.google.inject.Guice.createInjector(Guice.java:99)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at guice.NPEInjectionTest.test(NPEInjectionTest.java:23)
```
The test case:
```java
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Singleton;
public class NPEInjectionTest {
interface A { B getB(); }
interface B { }
interface Service { B getB(); }
@Test
public void test() {
Injector inj = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(B.class).toProvider(new Provider() {
@Inject Service service;
@Override
public B get() {
return service.getB();
}
});
}
}, new AbstractModule() {
@Override
protected void configure() {
bind(A.class).toProvider(new Provider() {
@Inject(optional=true) B b;
@Override
public A get() {
return () -> b;
}
});
}
@Provides @Singleton Service getService() {
throw new RuntimeException("Service producing C is not available");
// return () -> new B() { };
}
});
A a = inj.getInstance(A.class);
assertThat(a.getB()).isNotNull();
}
}
```
Contributor guide
Assessment
This issue has not been assessed yet.