I am using guice framework in my application. I have a scenario where a single class might require multiple instances of same interface C (but for different purposes) as shown in the example. I am trying to resolve this using the annotation facility in guice.
As shown in the example below, I want the config for ConcreteImpl also to be injected by guice. But the problem is the config for type1, type2 and type3 instances could be different. Assuming that I have the configurations for these instances apriori, is there a facility to inject them according to the context (denoted by annotation) of instance requesting the config?
class A {
@Inject
public A(@Purpose1 C type1, @Purpose2 C type2, @Purpose3 C type3) {
}
}
interface C {}
class ConcreteImpl implements C {
@Inject
public ConcreteImpl(ConcreteImplConfig config) {}
}
class ConcreteImplConfig {
String pty1;
String pty2;
}
My module binding is like this -
bind(C.class)
.annotatedWith(Purpose1.class)
.to(purpose1Cklass/**obtained from config**/);
bind(C.class)
.annotatedWith(Purpose2.class)
.to(purpose2Cklass/**obtained from config**/);
bind(C.class)
.annotatedWith(Purpose3.class)
.to(purpose3Cklass/**obtained from config**/);
And this is pretty much what I want to do
bind(ConcreteImplConfig.class)
.requestedThrough(Purpose1.class)
.toInstance(purpose1config);
bind(ConcreteImplConfig.class)
.requestedThrough(Purpose2.class)
.toInstance(purpose2config);
bind(ConcreteImplConfig.class)
.requestedThrough(Purpose3.class)
.toInstance(purpose3config);
I already had a look at assisted inject, which can inject a factory and then we use factory.create(config) but I am not inclined to that as the contracts tend to become slightly uglier and all the more i have all the configs at the start of my application and should be able to inject them.
This is the Robot Leg Problem. You need to create a private module for C.
abstract class CModule extends PrivateModule {
private final Class<? extends Annotation> annotation;
CModule(Class<? extends Annotation> annotation) {
this.annotation = annotation;
}
@Override protected void configure() {
bind(C.class).annotatedWith(annotation).to(C.class);
expose(C.class).annotatedWith(annotation);
bindConfig();
}
abstract void bindConfig();
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new CModule(Propsal1.class) {
@Override void bindConfig() {
bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
}
},
new CModule(Propsal2.class) {
@Override void bindConfig() {
bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
}
},
new CModule(Propsal2.class) {
@Override void bindConfig() {
bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
}
}
);
}