Reputation: 5837
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
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
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