xiaodududu / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Bug in com.google.inject.internal.Initializer #627

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I sometimes get this exception when using assisted inject:

Caused by: java.lang.NullPointerException: null
    at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:147) ~[guice-3.0.jar:na]
    at com.google.inject.internal.ConstantFactory.get(ConstantFactory.java:35) ~[guice-3.0.jar:na]
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031) ~[guice-3.0.jar:na]
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40) ~[guice-3.0.jar:na]
    at com.google.inject.Scopes$1$1.get(Scopes.java:65) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974) ~[guice-3.0.jar:na]
    at com.google.inject.spi.ProviderLookup$1.get(ProviderLookup.java:89) ~[guice-3.0.jar:na]
    at com.google.inject.multibindings.MapBinder$RealMapBinder$2.get(MapBinder.java:387) ~[guice-multibindings-3.0.jar:na]
    at com.google.inject.multibindings.MapBinder$RealMapBinder$2.get(MapBinder.java:383) ~[guice-multibindings-3.0.jar:na]
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40) ~[guice-3.0.jar:na]
    at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:38) ~[guice-3.0.jar:na]
    at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:62) ~[guice-3.0.jar:na]
    at com.google.inject.internal.SingleMethodInjector.inject(SingleMethodInjector.java:83) ~[guice-3.0.jar:na]
    at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110) ~[guice-3.0.jar:na]
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94) ~[guice-3.0.jar:na]
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254) ~[guice-3.0.jar:na]
    at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:53) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031) ~[guice-3.0.jar:na]
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974) ~[guice-3.0.jar:na]
    at com.proofpoint.experimental.json.JsonCodecFactory.createObjectMapper(JsonCodecFactory.java:121) ~[classes/:na]

After a bit of debugging I see that membersInjector is not initialized because 
InjectableReference.validate is not being called for some reason.

The obvious workaround it to add an if (membersInjector) validate(errors), but 
that seems like a hack.

In my code, if I put the assistedInject in a loop it works the second time 
through:

public class JsonCodecFactory
{
    private final Provider<ObjectMapper> objectMapperProvider;
    private final boolean prettyPrint;

    @Inject
    public JsonCodecFactory(Provider<ObjectMapper> objectMapperProvider)
    {
        this.objectMapperProvider = objectMapperProvider;
        this.prettyPrint = true;
    }

    public <T> JsonCodec<T> jsonCodec(Class<T> type)
    {
        Preconditions.checkNotNull(type, "type is null");

        return new JsonCodec<T>(createObjectMapper(), type);
    }

    private ObjectMapper createObjectMapper()
    {
        ObjectMapper objectMapper = null;
        while (objectMapper == null) {
            try {
                objectMapper = objectMapperProvider.get();
            }
            catch (Exception ignored) {
            }
        }
        if (prettyPrint) {
            objectMapper.getSerializationConfig().enable(INDENT_OUTPUT);
        }
        else {
            objectMapper.getSerializationConfig().disable(INDENT_OUTPUT);
        }
        return objectMapper;
    }
}

Original issue reported on code.google.com by d...@iq80.com on 1 May 2011 at 10:56

GoogleCodeExporter commented 9 years ago
Would you be to write a test case that reproduces the problem and attach it to 
this issue?

Original comment by sberlin on 3 May 2011 at 2:34

GoogleCodeExporter commented 9 years ago
I'm witnessing the same issue (intermittently) in a codebase that also combines 
Jackson JSON with Guice.  I don't have an isolated reproduction to offer, but I 
can add some additional context that I hope may help track down the cause:

I've noticed that the error occurs inside of a call to Injector.getInstance() 
which is invoked *within* the constructor of a guice-managed eager singleton: I 
have a singleton whose constructor loads some JSON configuration; during the 
JSON deserialization, we call injector.getInstance(...) to populate a field on 
a deserialized configuration object (this is perhaps a bad idea, but I would at 
least hope for more clear exception if we're doing something wrong).   This has 
worked for us in the past, but some recent change is frequently (but not 
always?!) resulting in a NPE (see below for the stacktrace).

One more note: the eagerSingleton constructor is actually being invoked A 
SECOND TIME when the exception is thrown; a breakpoint at the top of the 
constructor is hit twice prior to the exception.  I can't explain this; I 
wasn't able to locate any circular dependencies in this area of the code.

Hope this helps!

1) Error in custom provider, java.lang.NullPointerException

1 error
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1009)
  [... context elided ...]
Caused by: java.lang.NullPointerException
    at com.google.inject.internal.Initializer$InjectableReference.get(Initializer.java:147)
    at com.google.inject.internal.ConstantFactory.get(ConstantFactory.java:35)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    at com.google.inject.Scopes$1$1.get(Scopes.java:65)
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
    at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:38)
    at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:62)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:84)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    at com.google.inject.Scopes$1$1.get(Scopes.java:65)
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
    at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
    at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
    at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
    at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974)

Original comment by joshgr@gmail.com on 7 Aug 2011 at 12:14

GoogleCodeExporter commented 9 years ago
FYI, the singleton constructor happening twice is a separate bug, likely fixed 
by r1543, r1544, r1545, r1546 & r1547.  if _that_ bug still happens with the 
latest SVN, please open a separate issue?

a fix for this specific NPE should land in the next couple of days, i've 
isolated & fixed the problem locally.. code is just out for review.

Original comment by sberlin on 16 Oct 2011 at 4:23

GoogleCodeExporter commented 9 years ago
fixed in r1593.  please reopen a separate bug w/ the double-construction of the 
singleton if it's still happening on the latest SVN.  thanks!

Original comment by sberlin on 17 Oct 2011 at 12:09

GoogleCodeExporter commented 9 years ago
Issue 735 has been merged into this issue.

Original comment by sberlin on 13 Nov 2012 at 8:29

GoogleCodeExporter commented 9 years ago

Original comment by sberlin on 13 Nov 2012 at 8:30