Guice injection not working in web application

1,009 views
Skip to first unread message

Adil Quraish

unread,
Jun 18, 2018, 11:19:46 AM6/18/18
to google-guice

I am trying to get Guice to work in a web application deployed on JBoss EAP 6.4 When I try to step through the Guice code, I notice that the binding is happening. However, when I try to inject the bound object, I always get null. The following are the code changes I have done to enable Guice -


1) web.xml

<listener>
    <listener-class>com.univeris.guice.GuiceConfig</listener-class>
</listener>

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>


2) GuiceConfig

@Singleton
public class GuiceConfig extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
    Injector injector = Guice.createInjector(
            new ServletModule() {
                @Override
                protected void configureServlets() {
                    serve("/uif/*").with(UIFInitializeServlet.class);
                    serve("/upm/*").with(IDPServlet.class, ImmutableMap.of("instance-name","upm"));
                    serve("/uiw/*").with(IDPServlet.class, ImmutableMap.of("instance-name","uiw"));
                }
            },
            new MainModule()
    );

    return injector;
  }
}


3) MainModule

public class MainModule extends AbstractModule {

    @Override
    protected void configure() {
        install(new BankAccountModule());
        install(new CoreModule());
    }
}


4) BankAccountModule

public class BankAccountModule extends AbstractModule {
    @Override
    protected void configure() {
 bind(BankAccountProvider.class).toProvider(BankAccountGuiceProvider.class);      
 bind(BankAccountService.class).toProvider(BankAccountServiceProvider.class);
    }
}


5) BankAccountGuiceProvider

public class BankAccountGuiceProvider implements Provider<BankAccountProvider> {
    @Override
    public BankAccountProvider get() {
        return ProviderLocator.locateProvider(BankAccountProvider.class);
    }
}


6) BankAccountServiceUVS

@Stateless
@Interceptors(ServiceInterceptor.class)
public class BankAccountServiceUVS implements BankAccountService {

    @Inject
    private BankAccountProvider _bankAccountProvider;

    @Override
    public BankAccountCollection getAllBankAccounts(final Integer entityId, final String entityType) {
        BankAccountCollection retVal = _bankAccountProvider.getAllBankAccounts(entityId, 
        return PojoHelper.cloneObject(retVal);
    }
}


The _bankAccountProvider is always injected as null. I have been pouring through several forums for several days to no avail. Can someone point out what I am missing?

Stephan Classen

unread,
Jun 18, 2018, 6:44:07 PM6/18/18
to google...@googlegroups.com
Unless you tell guice that a dependency is optional it will never inject null. It would fail with an exception if it could not fullfil a dependency.

So for me the most likely cause of you seeing null is that the instance you are inspecting is created by calling new, using reflection or by another DI framework (like CDI or Spring).

Best strategy to debug this would be to make the field
_bankAccountProvider final. Then create a constructor to pass in the instance and annotate the constructor with @Inject.

Now you can place a breakpoint in the constructor. This will show you who is creating the instance. And if somebody is calling new the compiler may already tell you before you execute the code.

By the way: I would always favour constructor injection over field injection
- because it makes writing tests simpler (just call the constructor from your test class)
- an ugly constructor with 5+ arguments smells stronger than 5+ fields with annotation. And this is good because having that many dependency is often a sign that a class has too many responsebilities...

Thomas Broyer

unread,
Jun 19, 2018, 4:21:57 AM6/19/18
to google-guice


On Tuesday, June 19, 2018 at 12:44:07 AM UTC+2, scl wrote:
Unless you tell guice that a dependency is optional it will never inject null. It would fail with an exception if it could not fullfil a dependency.

So for me the most likely cause of you seeing null is that the instance you are inspecting is created by calling new, using reflection or by another DI framework (like CDI or Spring).

Best strategy to debug this would be to make the field
_bankAccountProvider final. Then create a constructor to pass in the instance and annotate the constructor with @Inject.

Now you can place a breakpoint in the constructor. This will show you who is creating the instance. And if somebody is calling new the compiler may already tell you before you execute the code.

…and in case something else than Guice has to create the instance, then you can injectMembers on the instance to have the fields (and methods) injected by Guice; either using a MembersInjector (that you could have @Inject⋅ed into your Provider) or Injector#injectMembers (which implies that you have access to the Injector at that point; the Injector can be @Inject⋅ed too into your provider, but I'd recommend using a MembersInjector instead).
 
By the way: I would always favour constructor injection over field injection
- because it makes writing tests simpler (just call the constructor from your test class)
- an ugly constructor with 5+ arguments smells stronger than 5+ fields with annotation. And this is good because having that many dependency is often a sign that a class has too many responsebilities...

+1
see also https://github.com/google/guice/wiki/MinimizeMutability (and other best practices in the wiki)

Adil Quraish

unread,
Jun 22, 2018, 1:21:38 PM6/22/18
to google-guice
Thanks. Based on your suggestion, I have modified BankAccountServiceProvider as follows -

public class BankAccountServiceProvider implements Provider<BankAccountService> {

   
@Inject
    private MembersInjector<BankAccountService> membersInjector;

   
@Override
    public BankAccountService get() {
       
BankAccountService bankAccountService = ServiceLocator.locateService(BankAccountService.class);
       
membersInjector.injectMembers(bankAccountService);
       
return bankAccountService;
   
}
}

Now I end up getting the following exception -

13:14:27,809 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/]] (ServerService Thread Pool -- 180) JBWEB000287: Exception sending context initialized event to listener instance of class com.univeris.guice.GuiceConfig: com.google.inject.internal.util.$ComputationException: com.google.inject.internal.util.$ComputationException: com.google.inject.internal.util.$ComputationException: java.lang.NullPointerException
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553) [guice.jar:]
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419) [guice.jar:]
at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041) [guice.jar:]
at com.google.inject.internal.FailableCache.get(FailableCache.java:50) [guice.jar:]
at com.google.inject.internal.ConstructorInjectorStore.get(ConstructorInjectorStore.java:49) [guice.jar:]
at com.google.inject.internal.ConstructorBindingImpl.initialize(ConstructorBindingImpl.java:125) [guice.jar:]
at com.google.inject.internal.InjectorImpl.initializeJitBinding(InjectorImpl.java:521) [guice.jar:]
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:847) [guice.jar:]
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:853) [guice.jar:]
at com.google.inject.internal.BoundProviderFactory.notify(BoundProviderFactory.java:44) [guice.jar:]
at com.google.inject.internal.ProcessedBindingData.runCreationListeners(ProcessedBindingData.java:50) [guice.jar:]
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:133) [guice.jar:]
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106) [guice.jar:]
at com.google.inject.Guice.jrCreateInjector(Guice.java:95) [guice.jar:]
at com.google.inject.Guice.createInjector(Guice.java:40004) [guice.jar:]
at com.google.inject.Guice.createInjector(Guice.java:72) [guice.jar:]
at com.google.inject.Guice.createInjector(Guice.java:62) [guice.jar:]
at com.univeris.guice.GuiceConfig.getInjector(GuiceConfig.java:13) [:18.6-SNAPSHOT]
at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:45) [guice-servlet.jar:]
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3339) [jbossweb-7.5.19.Final-redhat-1.jar:7.5.19.Final-redhat-1]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3780) [jbossweb-7.5.19.Final-redhat-1.jar:7.5.19.Final-redhat-1]
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:163) [jboss-as-web-7.5.12.Final-redhat-1.jar:7.5.12.Final-redhat-1]
at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:61) [jboss-as-web-7.5.12.Final-redhat-1.jar:7.5.12.Final-redhat-1]
at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:96) [jboss-as-web-7.5.12.Final-redhat-1.jar:7.5.12.Final-redhat-1]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [rt.jar:1.8.0_151]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [rt.jar:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [rt.jar:1.8.0_151]
at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_151]
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: com.google.inject.internal.util.$ComputationException: com.google.inject.internal.util.$ComputationException: java.lang.NullPointerException
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553) [guice.jar:]
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419) [guice.jar:]
at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041) [guice.jar:]
at com.google.inject.internal.FailableCache.get(FailableCache.java:50) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore.get(MembersInjectorStore.java:65) [guice.jar:]
at com.google.inject.internal.ConstructorInjectorStore.createConstructor(ConstructorInjectorStore.java:73) [guice.jar:]
at com.google.inject.internal.ConstructorInjectorStore.access$000(ConstructorInjectorStore.java:28) [guice.jar:]
at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:36) [guice.jar:]
at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:32) [guice.jar:]
at com.google.inject.internal.FailableCache$1.apply(FailableCache.java:39) [guice.jar:]
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:549) [guice.jar:]
... 32 more
Caused by: com.google.inject.internal.util.$ComputationException: java.lang.NullPointerException
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553) [guice.jar:]
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419) [guice.jar:]
at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041) [guice.jar:]
at com.google.inject.internal.FailableCache.get(FailableCache.java:50) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore.get(MembersInjectorStore.java:65) [guice.jar:]
at com.google.inject.internal.InjectorImpl.createMembersInjectorBinding(InjectorImpl.java:300) [guice.jar:]
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:814) [guice.jar:]
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205) [guice.jar:]
at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:853) [guice.jar:]
at com.google.inject.internal.SingleFieldInjector.<init>(SingleFieldInjector.java:41) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore.getInjectors(MembersInjectorStore.java:125) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore.createWithListeners(MembersInjectorStore.java:95) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore.access$000(MembersInjectorStore.java:34) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:42) [guice.jar:]
at com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:39) [guice.jar:]
at com.google.inject.internal.FailableCache$1.apply(FailableCache.java:39) [guice.jar:]
at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:549) [guice.jar:]
... 42 more
Caused by: java.lang.NullPointerException


Reply all
Reply to author
Forward
0 new messages