Search code examples
dependency-injectionjersey-2.0hk2

Jersy2 inject slf4j Logger


I'm trying to understand Jersey 2 development and context-dependency injection.

I don't understand how to inject into a resource an object that needs initialization parameters in the constructor. For example: I'd like to @Inject slf4j Logger, built using LoggerFactory.

My resource class is:

@Path("/myresource")
public class MyResource {
    @Inject
    private Logger log;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Answer status() {
        log.info("STATUS");
        return new Answer(200, "Server up and running @ "+ ZonedDateTime.now());
    }
}

My Resource config is:

public class MyAppextends ResourceConfig {
    public MyApp() {
        register(new MyBinder());
        packages(true, "my.packages");
    }
}

public class MyBinder extends AbstractBinder {

    @Override
    protected void configure() {
        bindFactory(MyLoggerFactory.class).to(org.slf4j.Logger.class);
    }
}

Finally, the Factory is:

public class MyLoggerFactory implements Factory<Logger> {

    @Override
    public Logger provide() {
        return LoggerFactory.getLogger(TYPE_FOR_LOGGING.class);
    }

    @Override
    public void dispose(Logger logger) {

    }
}

How can I specify TYPE_FOR_LOGGING as argument, in order to Inject the correctly initialized Logger in every resource I want?

Thanks


Solution

  • What you are looking for is called the InstantiationService. You can inject it into Factories to find out who is calling the factory inside of the provide method.

    Below find a code sample from the hk2 tests that illustrate the use of the InstantiationService.

    @Singleton
    public class CorrelationFactory implements Factory<PerLookupServiceWithName> {
        private final static PerLookupServiceWithName NULL_SERVICE = new PerLookupServiceWithName() {
    
            @Override
            public String getName() {
                return null;
            }
    
        };
    
        @Inject
        private InstantiationService instantiationService;
    
        /* (non-Javadoc)
         * @see org.glassfish.hk2.api.Factory#provide()
         */
        @Override @PerLookup
        public PerLookupServiceWithName provide() {
            InstantiationData data = instantiationService.getInstantiationData();
            if (data == null) {
                return NULL_SERVICE;
            }
    
            Injectee parent = data.getParentInjectee();
    
            if (parent == null) {
                return NULL_SERVICE;
            }
    
            Class<?> parentClass = parent.getInjecteeClass();
            if (parentClass == null) {
                return NULL_SERVICE;
            }
    
            Correlator correlator = parentClass.getAnnotation(Correlator.class);
            if (correlator == null) {
                return NULL_SERVICE;
            }
    
            final String fName = correlator.value();
    
            return new PerLookupServiceWithName() {
    
                @Override
                public String getName() {
                    return fName;
                }
    
            };
        }
    
        /* (non-Javadoc)
         * @see org.glassfish.hk2.api.Factory#dispose(java.lang.Object)
         */
        @Override
        public void dispose(PerLookupServiceWithName instance) {
            // DO nothing
        }
    
    }