Search code examples
javadependency-injectionguicehk2

How to configure HK2 for using Guice @Inject annotation from package com.google.inject?


I have a project based on Jersey 2, Guice 3.0 technologies. Since Jersey 2 framework uses HK2 I had to configure HK2-Guice bridge.

JerseyGuiceServletContextListener:

package com.example.core;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
public class JerseyGuiceServletContextListener extends GuiceServletContextListener {

    static Injector injector;

    @Override
    protected Injector getInjector() {
        injector = Guice.createInjector(new ServletModule() {
            @Override
            protected void configureServlets() {
                //some code here
            }
        });
        return injector;
    }
}

JerseyConfiguration:

package com.example.core;

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;

import javax.inject.Inject;
//...

class JerseyConfiguration extends ResourceConfig {

    @Inject
    public JerseyConfiguration(ServiceLocator serviceLocator) {
        packages("com.example.ws");

        GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
        GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
        guiceBridge.bridgeGuiceInjector(JerseyGuiceServletContextListener.injector);
    }
}

All works fine if I inject some class properties using javax.inject.Inject annotation. But when I use com.google.inject.Inject annotation my class properties aren't injected & I get NullPointerException when I tried to use this property.

How can I use com.google.inject.Inject annotation?


Solution

  • You would create your own InjectionResolver for com.google.inject.Inject. The following example would create one that works exactly like javax.inject.Inject. However there are probably subtle differences between google Inject and javax Inject which are NOT captured in the below implementation. If you rely on any of those differences you may need to get smarter in your implementation of the InjectionResolver. You would then also have to register your InjectionResolver in some Jersey bind call or another. Here is the basic implementation:

    @Singleton
    public class GuiceInjectResolver implements InjectionResolver<com.google.inject.Inject> {
        @Inject @Named(InjectionResolver.SYSTEM_RESOLVER_NAME)
        private InjectionResolver<Inject> systemResolver;
    
        /* (non-Javadoc)
         * @see org.glassfish.hk2.api.InjectionResolver#resolve(org.glassfish.hk2.api.Injectee, org.glassfish.hk2.api.ServiceHandle)
         */
        @Override
        public Object resolve(Injectee injectee, ServiceHandle<?> root) {
            return systemResolver.resolve(injectee, root);
        }
    
        /* (non-Javadoc)
         * @see org.glassfish.hk2.api.InjectionResolver#isConstructorParameterIndicator()
         */
        @Override
        public boolean isConstructorParameterIndicator() {
            return true;
        }
    
        /* (non-Javadoc)
         * @see org.glassfish.hk2.api.InjectionResolver#isMethodParameterIndicator()
         */
        @Override
        public boolean isMethodParameterIndicator() {
            return true;
        }
    
    }