Dropwizard HK2 injection

2019-02-26 11:09发布

问题:

im pretty new in working with dropwizard. Currently I'm trying to implement the HK2 dependency injection. That works pretty fine inside a resource but it doesn't work outside of a resource. Here is what I'm doing:

Client client = new JerseyClientBuilder(environment).using(configuration.getJerseyClientConfiguration()).build("contentmoduleservice");

    //DAOs
    ContentModuleDAO contentModuleDAO = new ContentModuleDAO(hibernate.getSessionFactory());
    ModuleServedDAO moduleServedDAO = new ModuleServedDAO(hibernate.getSessionFactory());

    //Manager
    ContentModuleManager moduleManager = new ContentModuleManager();
    EntityTagManager eTagManager = new EntityTagManager();
    ProposalManager proposalManager = new ProposalManager(client, configuration);

    environment.jersey().register(new AbstractBinder() {
        @Override
        protected void configure() {
            bind(eTagManager).to(EntityTagManager.class);
            bind(contentModuleDAO).to(ContentModuleDAO.class);
            bind(moduleServedDAO).to(ModuleServedDAO.class);
            bind(proposalManager).to(ProposalManager.class);
            bind(moduleManager).to(ContentModuleManager.class);
        }
    });

I create Instance of the classes I want to be injectible and bind them.

Inside my resource the injection works:

@Api
@Path("/api/contentmodule")
public class ContentModuleResource {

    static final Logger LOG = LoggerFactory.getLogger(ContentModuleResource.class);
    static final int MAX_PROPOSALS_PER_MODULE = 10;

    @Inject
    private ContentModuleDAO contentModuleDAO;

    @Inject
    private EntityTagManager eTagManager;

    @Inject
    private ProposalManager proposalManager;

    @Inject
    private ContentModuleManager contentModuleManager;

All these variables are filled with an Instance of the right class.

The problem is: The ContentModuleManager should also get some of these classes via injection:

public class ContentModuleManager {

@Inject
private ContentModuleDAO contentModuleDAO;

@Inject
private ProposalManager proposalManager;

@Inject
private ModuleServedDAO moduleServedDAO;

But those are null. Can somebody explain a dropwizard noob why this happens and how I can fix this? :D

Thanks!

回答1:

If you are going to instantiate the service yourself then it is not going to go through the DI lifecycle and will never be injected. You can let the container create the service if you just register the services as a class

bind(ContentModuleManager.class)
    .to(ContentModuleManager.class)
    .in(Singleton.class);

On the other hand, if you are creating all the services yourself and you have all of them available, why don't you just not use the DI container at all? Just pass all the services through the constructor. Whether you are using constructor injection1 or manually passing through the constructor, getting the service through the constructor is good practice anyway, as it allows for easier testing of the service.


1 - Constructor injection

private Service service;

@Inject
public OtherService(Service service) {
   this.service = service;
}