Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In the project I'm working on, I'm using Guice and trying to do as much as possible with Dependency Injection. However, there's one little snag; many of my objects rely on an object Context. This is an immutable object but has some information which most of the other objects need to function properly. It never changes for classes that are all working within the same Context, but my application must be able to support different Contexts at the same time, in the same scope. I can think of three ways to solve my problem:

  1. Currently, I've found myself writing lots of code with AssistedInject, which almost always has methods like Factory.create(Context c). All my code that depends on Context is being created in this manner, even if they are otherwise simple.

  2. I'm starting to consider using Providers, and changing every line of factory.create(context) to obj = provider.get(); obj.setContext(c); but I don't want to rely on my code to do both calls, I like that the compiler makes sure that every object has it's context and that the context cannot change (it never will).

  3. My research pointed me to this thread: http://stackoverflow.com/questions/16316719/guice-assisted-injection-deeper-down-the-dependency-hierarchy The idea of pairing each Context to a childInjector which has one line bind(Context.class).toInstance(ContextFactory.makeInstance(args)), but I'm not sure how to ensure that everything is using the correct child injector. This seems like it might be best, but other than that thread (which isn't my scenario) I'm not sure how to do it, or if it's right for my situation.

Here's an sscce of what might be done by option 3:

public class GuiceChildTest {
    public static void main(String... args) {
        Injector inj = Guice.createInjector(new ParentModule());
        Injector fooChildOne = inj.createChildInjector(new FooModule(new Foo(10)));
        Injector fooChildTwo = inj.createChildInjector(new FooModule(new Foo(20)));

        Bar bar = fooChildOne.getInstance(Bar.class);
        System.out.println(bar.baz());

        bar = fooChildTwo.getInstance(Bar.class);
        System.out.println(bar.baz());
    }

    private static class ParentModule extends AbstractModule {
        @Override
        protected void configure() {
        }
    }

    private static class Bar {
        private MyInterface intf;
        @Inject
        public Bar(MyInterface in) {
            this.intf = in;
        }

        public int baz() {
            return intf.doSomething();
        }
    }

    private static class FooModule extends AbstractModule {
        private Foo f;
        public FooModule(Foo f) {
            this.f = f;
        }

        @Override
        protected void configure() {
            bind(MyInterface.class).toInstance(f);
        }   
    }   

    private static class Foo implements MyInterface {
        private int i;
        public Foo(int i) {
            this.i = i;
        }
        @Override
        public int doSomething() {
            return i;
        }
    }

    private static interface MyInterface {
        int doSomething();
    }
}
share|improve this question
2  
This seems like a lot of hoop jumping just to pass an object into a constructor. If the context exists at creation time, I would just do that rather than using the new shiny tool. If not, then creating a container with your new context and the 'standard' factories seems most appropriate. –  Telastyn Jun 18 '13 at 0:26
    
Could you use ThreadLocal and pick the context up from there? I'm not sure what causes your different contexts to get created and used. –  Michael Gantz Jan 17 at 19:02
    
Have you thought about self initiated member injection? This is an approach I use for injection in RESTlet (RESTlets also require contexts). Admittedly, it has limitations (all my restlets must inherit from an abstract base class that performs the injection), but it's easy to use and understand and can support objects created outside of the DI framework. –  tom Jan 21 at 22:36
    
Based on requirements you could also used named injection. That way each class defines which of the named context vertical it belongs to an injects the correct instance of context. –  Usman Ismail Jun 27 at 15:01
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.