3

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.

amrk7
  • 1,144
  • 4
  • 13
  • 29
  • 1
    Possible duplicate of [How to implement the "robot legs" use case with Google Guice?](http://stackoverflow.com/questions/35784112/how-to-implement-the-robot-legs-use-case-with-google-guice) – Michael Lloyd Lee mlk Mar 10 '16 at 13:03
  • Oh yes indeed! I had trouble correlating with that example. Its so clear now. :) Thanks!! – amrk7 Mar 10 '16 at 18:18

1 Answers1

2

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());
                    }
                }
                );
    }
Michael Lloyd Lee mlk
  • 14,109
  • 3
  • 40
  • 79