I have two classes, Foo<T> and Bar, which depend on each other, as well as various other classes. I am using Dagger-2 for dependency injection, but if I naively add the circular dependency, Dagger hits a stack overflow at runtime. What's a good way to refactor the classes to fix this, while still using Dagger to inject all the other dependencies, and with minimal duplication and changes to existing calls?
The easy way out is to use Lazy<T> on one side.
Lazy<Foo> foo;
#Inject
Bar(Lazy<Foo> foo) {
this.foo = foo;
}
// use foo.get(); when needed
After an excessive amount of thought and talks with coworkers, we ended up doing the following:
class Foo<T> extends FooWithoutDep<T> {
#Inject Foo(Bar bar, OtherDep1 dep1, OtherDep2 dep2) {
super(dep1, dep2);
setBarDep(bar);
}
}
class FooWithoutDep<T> {
//Field declarations elided
#Inject FooWithoutDep(OtherDep1 dep1, OtherDep2 dep2) {
//Normal constructor stuff
}
void setBarDep(Bar bar) { this.bar = bar; }
//The rest of the actual logic
}
class Bar {
//Field declarations elided
#Inject Bar(FooWithoutDep<Thing> foo, OtherDep3 dep3) {
this.foo = foo;
this.foo.setBarDep(this);
this.dep3 = dep3;
}
//Code that uses Foo and the other dependencies
}
Explaining this -- we moved the actual logic of Foo into a parent class (FooWithoutDep), that took the circular dependency as a settable field rather than a constructor parameter. Then the original class just contained a constructor that took the circular dependency and called the setter. The other class, Bar, depended on the parent (FooWithoutDep), and called the setter explicitly, passing itself (this). This enables all the existing references to the class to remain the same, while still using Dagger to inject all the dependencies.
This seemed confusing enough to be worth writing up here.
This is how I resolved it, without parent classes.
Class 1: Engine.
(in component interface)
#Provides
public Engine myEngine(Context context) {
return new Engine (context);
}
Class 2: Parts. Engine also needs Parts instance but the creation is delayed.
#Inject
public Parts(Context context, Engine engine) {
this.context = context;
this.engine= engine;
engine.setParts(this);
}
Circular dependency can be achieved but one class must be initiated first before the other.
Again, if possible, refactor code to avoid circular DI.
Related
My question may be a tad misleading but i'm not sure of any other way to ask it. Basically I'm having trouble discerning the differences between 'dependency injection' and 'java composition'. They both involve using variables to access classes. With dependency injection you pass an already instantiated instance (class A) created outside of Class B into the class B via constructor. With Java composition it seems you create a new instance of Class A inside of Class B since Class B cannot exist without Class A. If I'm interpreting this wrong then I'm not understanding the design pattern difference between dependency injection and Java composition since you have to do the same thing to use variables to access other class objects.
Anywho, using mockito, how would I go about testing this Java composition pattern?
What i'm needing help with:
Class Bar cannot exist without Class Foo (Java Composition: Has-A). therefore, i create a new instance of Foo inside bar instead of injecting an already created instance of Foo into Bar (dependency injection).
How do I properly set this up in Mockito so that I can mock a class of Foo inside Bar? My pseudocode is below.
Create interface
public interface MyRequiredObjectsInterface {
public String stringOne();
public List<String> listOne();
}
Create Class 'Foo' that implements Interface
public class Foo implements MyRequiredObjectsInterface {
public Foo() {
//Empty for example
}
#override
public String stringOne() {
return "StackOverflow Help";
}
#override
public List<String> listOne() {
return new List<String>();
}
}
Create Class 'Bar' that cannot exist without class 'Foo'
public class Bar implements MyRequiredObjectsInterface {
Private Foo foo;
public Bar() {
*/
Java composition pattern. With dependency injection, I would just pass an instance
of foo through the constructor. I dont know why you dont do this with Java composition
pattern and if you do, then I dont understand the difference in design patterns with this.
/*
foo = new Foo();
}
#override
public String stringOne() {
return foo.stringOne();
}
#override
public List<String> listOne() {
return foo.listOne();
}
}
Ok, so now I've shown you the setup. In Mockito, how would I test this Java composition patter? The following code does not work because I cannot mock an instance of Foo inside Bar since the instance is created inside Bar.
public class BarTest {
private Foo foo;
private Bar bar;
#Before
public void setUp()
this.bar = new Bar();
// There is no way to get this inside Bar...
this.foo = mock(Foo.class);
}
#test
public void testListOne() {
*/
NOTE how that if you look at the code above, it calls the object from Foo -- foo.listOne();
In a real world scenario, this would be more complicated logic here as Foo
may perform more complex logic that may need to be mocked out for testing
but to show my design of the application i used pseudocode to get the point
across to show what im struggling grasping with the Java composition design pattern.
This would run into errors since I cannot mock this with Java composition pattern.
*/
assertEquals(bar.listOne().equals(...)
}
Any thoughts on helping me solve my conundrum? Here are some references I used that didnt answer my question
Difference between dependency and composition?
https://www.softwaretestinghelp.com/composition-in-java/
I have one base class and 2 derived classes. I will attempt to explain with a very simplified version:
public class AllIntegers{
List<Integer> myList;
BehaviorSubjec<Integer> behaviorSubject;
#Inject
public AllIntegers(List<Integers> allIntegers) {
behaviorSubject = BehaviorSubject.create();
//some logic
}
public BehaviorSubject<Integer> getAllIntegersBSAsObservable() {
return this.behaviorSubject.asObservable();
}
}
public class OddIntegers extends AllIntegers {
List<Integer> myList;
#Inject
public OddIntegers(... some dependencies...) {
/* ... some logic ... */
//Getting observable from parent
getAllIntegersBSAsObservable.subscribe(new Subscriber(...));
}
}
public class EventIntegers extends AllIntegers {
List<Integer> myList;
#Inject
public EventIntegers(... some dependencies...) {
/* ... some logic ... */
//Getting observable from parent
getAllIntegersBSAsObservable.subscribe(new Subscriber(...));
}
}
My Roboguice module file looks like this:
bind(IAllIntegers.class).to(AllIntegers.class).in(Scopes.SINGLETON);
bind(IOddIntegers.class).to(OddIntegers.class).in(Scopes.SINGLETON);
bind(IEventIntegers.class).to(EventIntegers.class).in(Scopes.SINGLETON);
Again, I OVER simplified here to make it easier to write and understand.
The problem is that Roboguice creates an instance of AllIntegers.class as it should. I have to however add an empty constructor to the AllIntegers.class for the compiler to not complain, this of course causes OddIntegers and EventIntegers to EACH get their OWN instance of AllIntegers, so both children get different instances of the observable while the singleton base class also gets its own (this is the one I actually want), so when I fire onNext on the behavior subject, the children do not react because the behavior subject is different.
Should I be using composition instead of inheritance?
I don't think Roboguice is the problem, this is standard behaviour. You're calling getAllIntegersBSAsObservable, an instance method, wich returns this.behaviorSubject.asObservable(); an instance field. Even though all instances are singletons, they are still separate instances, so they each have their own instance of behaviorSubject.
A possible fix is to make behaviorSubject a static field.
I read a lot of material on the #Scope annotation but still not fully understanding if what I know is correct.
Can someone explain what exactly is #Scope for? Where is it used? How is it used?
Is it only used when defining the component?
Also is a scope defined like this?:
#Scope
public #interface SomeScope {
}
And used like this?:
#SomeScope
#Component(modules = {
HeaterModule.class,
PumpModule.class
})
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
CoffeeMaker maker();
}
The definition of scopes for Java EE applications states the following:
For a web application to use a bean that injects another bean class,
the bean needs to be able to hold state over the duration of the
user’s interaction with the application. The way to define this state
is to give the bean a scope.
Let's associate it with Android. Scopes impose certain limitations in terms of dependencies lifecycle provided by a scoped provider.
For example, let's say we want to be provided with #Singleton dependency obtainable from #ActivityScoped component. The component lives as long as the Activity. Once activity is destroyed and created again, our component is instantiated accordingly and our '#Singleton' dependency is also created once again.
Summing up, our #Singleton dependencies live as long as the #Components they are associated with - this is I think most practical explanation.
Internally, once Dagger notifies within the #Component the provision method with the specified scope, it creates a ScopedProvider for dependency provision. Otherwise, a Factory is created.
The ScopedProvider's get method is a double-check singleton method:
public T get() {
// double-check idiom from EJ2: Item 71
Object result = instance;
if (result == UNINITIALIZED) {
synchronized (this) {
result = instance;
if (result == UNINITIALIZED) {
instance = result = factory.get();
}
}
}
return (T) result;
}
To see a practical #Scope usage you can take a look at one of the examples of mine:
https://github.com/dawidgdanski/AccountAuthenticatorExample
Hope, that was helpful somehow.
EDIT 1:
The article provided by #Fshamri explains it even better.
EDIT 2:
Let's consider the following structure :
The Component:
#ActivityScope //Dagger ignores the annotation put atop the #Component. I put it there just for readability
#Component(dependencies = DependencyGraph.class,
modules = {ActivityModule.class})
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SignUpActivity signUpActivity);
void inject(SignInActivity signInActivity);
And the module supplying the dependencies:
#Module
public class ActivityModule {
private final Activity activity;
public ActivityModule(Activity activity) {
this.activity = activity;
}
#Provides
#ActivityScope
MainView provideMainView() {
return (MainView) activity;
}
#Provides
SignInView provideSignInView() {
return (SignInView) activity;
}
}
The #ActivityScope extends the #Scope annotation - it is interpreted by Dagger the same way as the #Singleton is. The ActivityModule provides 2 views: the #ActivityScoped MainView and the SignInView without any scope. During the compilation time Dagger's annotation processor creates Providers for both views. The difference between the MainView's and the SignInView's generated Provider is that for the MainView Dagger generates the ScopedProvider (because we explicitly request this kind of provider with #ActivityScope) whereas for the SignInView Dagger generates regular Factory provider.
The contract of the ScopedProvider looks like the one above. The contract for the Factory provider, however, looks the following way:
#Generated("dagger.internal.codegen.ComponentProcessor")
public final class ActivityModule_ProvideSignInViewFactory implements Factory<SignInView> {
private final ActivityModule module;
public ActivityModule_ProvideSignInViewFactory(ActivityModule module) {
assert module != null;
this.module = module;
}
#Override
public SignInView get() {
SignInView provided = module.provideSignInView();
if (provided == null) {
throw new NullPointerException("Cannot return null from a non-#Nullable #Provides method");
}
return provided;
}
public static Factory<SignInView> create(ActivityModule module) {
return new ActivityModule_ProvideSignInViewFactory(module);
}
}
Conclusions:
1. The ScopedProvider is a classical double-check singleton pattern. It guarantees to create only one instance of the dependency.
2. The Factory's get() method just distributes the dependency from the module which means it can distribute new instance of the dependency each time it is requested (in fact, in the example the Activity is only cast to the SignInView which still gives us a single instance but this is copy-pasted logic from my example).
3. Dagger cares about #Scopes provided along with provision methods in the #Modules, not the #Components.
I encourage you to download the sample and build the project, then to see the contract of the generated Dagger components and modules.
Hope this is more understandable now.
have you looked at this article?
In Dagger 2 scopes mechanism cares about keeping single instance of
class as long as its scope exists. In practice it means that instances
scoped in #ApplicationScope lives as long as Application object.
#ActivityScope keeps references as long as Activity exists (for
example we can share single instance of any class between all
fragments hosted in this Activity). In short - scopes give us “local
singletons” which live as long as scope itself.
A question about Guice. I'm still learning it, but I can understand the fundamentals.
This question was already asked a couple of times on the net, but never with a concrete answer(none that I could find).
Say I have a situation like on the picture(a similar example was somewere on the net).
public class Dog {}
public class Walk implements Walkable {
private final Dog dog;
private final boolean leash;
#Inject
public Walk(Dog dog, #Assisted boolean leash) {
this.dog = dog;
this.leash = leash;
}
public void go() {
}
}
public interface Walkable {
void go();
}
public interface WalkFactory {
Walk create(boolean leash);
}
public class AssistedMain {
public static void main(String[] args) {
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
install(new FactoryModuleBuilder().
implement(Walkable.class, Walk.class).
build(WalkFactory.class));
}
});
Walk walk = i.getInstance(WalkFactory.class).create(true);
}
}
That's all great. But the question is - can I, somehow, reinject that object instance to the "container"(injector) to be used on the classes that rely on this dependency.
So, lets add a interface Person, class PersonImpl.
The new classes source are:
public interface Person {
void walkDog();
}
public class PersonImpl implements Person {
private Walkable walkable;
#Inject
public PersonImpl(Walkable walkable) {
this.walkable = walkable;
}
public void setWalkable(Walkable walkable) {
this.walkable = walkable;
}
public void walkDog() {
walkable.go();
}
}
So, the question is - am I, somehow able to actually inject this particular instance into the added object. This is a simple example, but we can presume there are 10 levels of classes below this one.
The solution I found is not very flexible. Something like:
Injector i = Guice.createInjector(new SimpleModule(false, dog));
And then bind to concrete instance. That's not very dynamic. Basically, every time I need a different runtime/dynamic parameter I have to recreate the injector.
The Provider<T> is nice, the FactoryModuleBuilder helps, but how can I inject the objects back?
Are there more dynamic solutions to this problem?
Thanks.
MPierce - agreed. Ill try to explain the way i visualized the problem(you can correct me if im wrong).
Being originaly derived from a "service locator" pattern, the idea that it can manage more than services is optimistic to say the least.
We could split the application into Service and Data classes, or you could say that we have application and infrastructure code - "Dependency Injection", a great book.
So, basicly, dependecy injection, and dependency injection frameworks in general are great. For solving infrastructure, or "service" code.
Any dynamic(runtime) parameters being injected into the Container/Injector are basicly forcing you to end the object graph.
For example, we have the folowing design:
EmailMessage is a runtime parameter. It can be "injected" into email service outside the Container/Injector, but it ends the object graph. If we want to request EmailDispatcher, after we injected the EmailMessage into EmailService(which is, I repeat, done outside injector), we could no longer fetch EmailDispatcher from the injector.
Then, you could redesign your model so it "fits" into the Container/Injector concept of dynamic parameters.
But then again, you forced the design, and suddenly, EmailDispatcher has too many responsibilites. It could be used in such a context, where you dont have many infrastructure classes.
And when you have a design like you have in the third example picture, you cannot use the Injector/Container to fetch you a NextService3 instance(nor any below the level of EmailDispatcher).
The problem being - if you have any dynamic(runtime) parameters, you can only use dependency injection for classes above the class that requires a dynamic parameter, you can forget the classes below.
Phew.
Correct?
Part of the problem depends on how you're resolving that 'false' is the thing you want to set for the leash field. Is that coming from config data or what?
A provider method may be helpful...
class FooModule extends AbstractModule {
...
#Provides
Walkable getWalkable(Dog dog) {
boolean leash = getBooleanFromSomewhere();
return new Walk(dog, leash);
}
}
If you can clarify where that boolean is coming from, it'll help me to understand what type of approach is applicable.
You can use custom scopes, much like when using guice servlets. That way you can create your instance, and then seed it in the injector.
I have a situation where I need to use Guice 3.0 to instantiate my object but one of the values will change potentially with each instance. I cannot bind that value's type and I won't know until I need to create the instance.
For instance:
public class Foo {
public Foo(Bar bar, Baz baz) {...}
}
I want Guice to inject the Bar param but I won't know Baz until I need Foo. The value isn't scope-specific (e.g. RequestScope) either.
The whole reason I want this object fully instantiated by Guice is because I need method interception. In Guice, "manually constructed instances do not participate in AOP".
I've tried to do this with Provider<Foo> but that only allows me public Foo get() { ... }.
It would be a configuration nightmare to have to create a provider for every possible value of Baz, so I can't simply have Baz be defined in FooProvider's constructor.
I feel like I'm missing something fundamental here. Perhaps it is because it is the last thing I'm doing on a Friday. Any ideas would be appreciated.
Edit: The answer below to use "assisted injection" seems to only work if you have the ability to edit the source of Foo. Foo may actually be outside of my control for some instances. And if I create the instances myself (i.e., implement my own factory) then Guice-AOP method interceptors don't seem to ever know about the object.
It looks like "assisted injection" might be a solution:
http://google-guice.googlecode.com/svn/trunk/latest-javadoc/com/google/inject/assistedinject/FactoryModuleBuilder.html
Except it doesn't work if you don't have access to annotate the constructor of Foo.
EDIT: what I have found is that I am able to add the assisted injection annotations by extending the type and adding them to the constructor that I wish to use:
public class AssistedFoo extends Foo {
#AssistedInject
public AssistedFoo(
Bar bar,
#Assisted Baz baz) {
super(bar, baz);
}
}
Then use this extended implementation in the assisted injection registration:
public interface FooFactory {
Foo create(Baz baz);
}
//...
install(new FactoryModuleBuilder()
.implement(Foo.class, AssistedFoo.class)
.build(FooFactory.class));
The extra inheritance class is only needed when you don't have access to change Foo. Obviously this workaround wouldn't work if the class is final.
If you can't use Assisted Inject to create the factory, you can just write your own factory implementation:
// same as for Assisted Inject
public interface FooFactory {
Foo createFoo(Baz baz);
}
public class FooFactoryImpl implements FooFactory {
private final Bar bar;
#Inject
public FooFactoryImpl(Bar bar) {
this.bar = bar;
}
public Foo createFoo(Baz baz) {
return new Foo(bar, baz);
}
}
Then just bind(FooFactory.class).to(FooFactoryImpl.class) and inject a FooFactory wherever you need to create Foos.
Edit:
An exceedingly awkward workaround you could do (that would allow method interception on Foo):
bind(Foo.class).toConstructor(...)
Define and bind the SimpleScope scope described here.
bind(Baz.class).in(BatchScoped.class)
Injected a Provider<Foo> and SimpleScope into the class that wants to create Foos.
Then:
public Foo someMethod(Baz baz) {
simpleScope.enter();
try {
simpleScope.seed(Baz.class, baz);
/*
* We're in the scope for Baz, so it can be injected normally into Foo
* right now.
*/
return fooProvider.get();
} finally {
scope.exit();
}
}
You could even use method interception on such a method to handle the scoping, if the method isn't private... though it might not be a great idea since it would be confusing if you didn't use the parameter at all in the method but it had to be there to work.