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
TestClass
orRealClass
to be bound to all injections ofInterfaceA
andInterfaceB
; 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
TestClass
orRealClass
to a singleton instance in that injector. The problem is, whetherTestClass
orRealClass
is 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 bindInterfaceA
toTestClass
, 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
TestClass
andRealClass
. 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
RealClass
in the parent fails withNo scope is bound to name.package.WhateverScope.
because it seems to insist that the
WhateverScope
is 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: