2

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

besil
  • 1,308
  • 1
  • 18
  • 29

1 Answers1

2

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
    }

}
jwells131313
  • 2,364
  • 1
  • 16
  • 26
  • Thank you, this is exactly what I needed. Could you please point some HK2 documentation other than the JavaDoc? – besil Sep 08 '16 at 18:17
  • The only other documentation I could find about InstantiationService is in the Factory javadoc. That should probably be fixed, it probably needs a little more explanation than what is in the current documentation – jwells131313 Sep 08 '16 at 19:12