Bombe
Bombe

Reputation: 83879

Injecting values depending on the object to be injected

I have the following scenario:

public class InjectionTest {
    private static class Sub {
        @Inject private final String value = null;
    }
    private static class General {
        @Inject private final Sub sub = null;
    }
    private static class MainOne {
        @Inject private final General general = null;
    }
    private static class MainTwo {
        @Inject private final General general = null;
    }
    public static void main(String... arguments) {
        Injector injector = Guice.createInjector(new AbstractModule() {
            @Override protected void configure() {
                /* DO MAGIC */
            }
        });
        MainOne mainOne = injector.getInstance(MainOne.class);
        MainTwo mainTwo = injector.getInstance(MainTwo.class);
        assertThat(mainOne.general.sub.value, is("one"));
        assertThat(mainTwo.general.sub.value, is("two"));
    }
}

I want the value accessible from the instance of MainOne to be "one" and the value accessible from the MainTwo instance to be "two". I have tried the following:

(Of course the real scenario is more complicated, as always: I have a GuiceServletContextListener and a ServletModule and I’m trying to reuse a couple of classes/services among all created Servlet instances but also need a couple of specialized modules that are requested from the servlets.)

Am I missing anything? Is there a (relatively) easy way to achieve what I want?

Upvotes: 0

Views: 202

Answers (1)

eiden
eiden

Reputation: 2349

First off, you shouldn't inject into final fields (see comments). I suggest that you remove the final modifier, or use constructor injection.

It's possible to solve your example by using private modules. But I don't consider this an "easy" solution.

    Injector injector = Guice.createInjector(new PrivateModule() {
        @Override
        protected void configure() {
            bind(String.class).toInstance("one");
            bind(MainOne.class);

            expose(MainOne.class);
        }
    }, new PrivateModule() {
        @Override
        protected void configure() {
            bind(String.class).toInstance("two");
            bind(MainTwo.class);

            expose(MainTwo.class);
        }
    });

I think you're better off using either @Named or creating your own binding annotation.

Also read the wiki page on the "robots leg" problem: https://github.com/google/guice/wiki/FrequentlyAskedQuestions#how-do-i-build-two-similar-but-slightly-different-trees-of-objects

Upvotes: 2

Related Questions