This question is a continuation of Using guice for a framework with injected classes, proper way to initialize?, which I've tried to implement, and also tried other ways to get around the issue, but nothing has worked so far.
The main issue is this. I have an InterfaceA and InterfaceB that are exposed in different parts of the API. There are two classes that implement both of these interfaces, TestClass and RealClass, so that depending on whether I'm testing or doing something else, I can do the following:
bind(InterfaceA.class).to(TestClass.class);
bind(InterfaceB.class).to(TestClass.class);
or, for production:
bind(InterfaceA.class).to(RealClass.class);
bind(InterfaceB.class).to(RealClass.class);
I have two requirements for using these classes:
- I need the same instance of
TestClassorRealClassto be bound to all injections ofInterfaceAandInterfaceB; so, like a singleton pattern, except that: - The singleton is only for a specific scope or child injector, many of which are created during the execution of the program.
The default no-scope approach causes multiple instances of RealClass/TestClass to be created for each interface injection. I don't want that, so I've tried implementing this with scopes, child injectors, and other methods. Nothing has worked:
- Child injector approach: I create a new injector and try to bind the
TestClassorRealClassto a singleton instance in that injector. The problem is, whetherTestClassorRealClassis being used is configured in the parent injector, and since it's a singleton, it's already instantiated (unless inStage.DEVELOPMENT). There's no way to bindInterfaceAtoTestClass, in the parent injector, for example, and then re-bind it as a singleton in the child injector. - Scope approach: I create a custom scope and annotate
TestClassandRealClass. Then, I enter and exit this scope to get single instances in that scope. The problem is that my code is multithreaded and having the scope change from one thread affects what the global injector can see and mucks up creating other instances. Combined child injector and scope approach. I tried creating a child injector for each use of this custom scope, but then binding
RealClassin the parent fails withNo scope is bound to name.package.WhateverScope.because it seems to insist that the
WhateverScopeis available all the time, not just in the child injector.
All these problems seem to be due to the fact that I need to be able to configure whether to use TestClass or RealClass in the parent, but then to be able to instantiate them later, as a singleton, for a specific group of objects. I'm pulling my hair out over how to get this done!
By the way, the documentation for Guice scopes is horrible and almost impossible to understand. This article is the only one that has gotten me anywhere: