RP-
RP-

Reputation: 5837

Inject guice managed dependency in a non guice class

I have a class (CustomConnectionProvider) which will be instantiated by a third party library (hibernate) using class.forName().newInstance(). I need to inject a guice managed dependency say MyDatabaseFactory which will provide data sources for multi-tenancy.

I can not directly @Inject the MyDatabaseFactory, because CustomConnectionProvider is not a managed bean. And I have no control over how it is being created.

I just started with Guice as part of a Play application. Any examples or ideas would be appreciated, I am looking for a solution like ServiceLocator.

Fixed for specific case Luckily, Play.application() provides a static method to get the injector and I'm using it to get the instance of my Factory. I still want to know if I have to fix it without play.

Update for Play 2.5 Play.application() is deprecated in 2.5. We need to use static injection as robert suggested.

Upvotes: 3

Views: 2652

Answers (2)

RP-
RP-

Reputation: 5837

Actually, the requestStaticInjection is not a recommended way. As the this link explains (This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.), it creates many problems under few circumstances. The behaviour is not consistent and the injection is not successful all the times.

I had to take slightly different approach: My case is little complicated, the instance of my class will be created by Hibernate using Class.forName(), this may be yet another case where static injection may fail.

I had to create a Singleton factory which will be initialized and bind to Guice Injector at the start of the module creation, this factory will hold the actual bean which I need to inject into my actual class. It provides a static method to get the required bean.

public Class RequiredBeanFactory {
        private static RequiredBean bean;
        //note this is a package private
        RequiredBeanFactory(RequiredBean bean) {
            this.bean = bean;
        }

        public static RequiredBean getBean() {
            return bean;
        }
    }

In my Module, I am initializing it and binding.

public class MyModule extends AbstractModule {
    private final RequiredBean bean;

    @Inject
    public MyModule(RequiredBean bean) {
        this.bean = bean;
    }

    protected void configure() {
        RequiredBeanFactory factory = new RequiredBeanFactory(this.bean);
        bind(RequireBeanFactory.class).toInstance(factory);
    }
}

In my HibernateCustom class, I just use RequiredBeanFactory.getBean().

This is kind of a hack, may have the same side effects as Guice mentioned, but it is in my control and the behaviour is consistent.

Upvotes: 1

robert
robert

Reputation: 978

You can use static injection. See https://github.com/google/guice/wiki/Injections

It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. Use

requestStaticInjection() 

in a module to specify classes to be injected at injector-creation time:

@Override public void configure() { 
requestStaticInjection(ProcessorFactory.class); ... }

Guice will inject class's static members that have the @Inject annotation.

Upvotes: 2

Related Questions