Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Violating @Singleton definition and bypassing "depends on more than one scoped component" error #1225

Closed
guliash opened this issue Jul 17, 2018 · 3 comments

Comments

@guliash
Copy link

guliash commented Jul 17, 2018

Hi. I found example where we can create two singletons in hierarchy:

package com.guliash.dagger;

import dagger.Component;
import dagger.Module;
import dagger.Provides;

import javax.inject.Inject;
import javax.inject.Scope;
import javax.inject.Singleton;

public class Main {

    public static void main(String[] args) {
        ComponentC componentC = DaggerComponentC.builder()
                .markerA(DaggerComponentA.create())
                .markerB(DaggerComponentB.create())
                .build();

        System.out.println(componentC.myClassA().myClass);
        System.out.println(componentC.myClassB().myClass);
    }

}

@Singleton
class MyClass {

    @Inject
    public MyClass() {

    }
}

class MyClassA {
    MyClass myClass;

    @Inject
    public MyClassA(MyClass myClass) {
        this.myClass = myClass;
    }
}

interface MarkerA {
    MyClassA myClassA();
}

@Singleton
@Component
interface ComponentA extends MarkerA {

}

class MyClassB {
    MyClass myClass;

    @Inject
    public MyClassB(MyClass myClass) {
        this.myClass = myClass;
    }
}

interface MarkerB {
    MyClassB myClassB();
}

@Singleton
@Component
interface ComponentB extends MarkerB {

}

@Scope
@interface ScopeC {}

@ScopeC
@Component(dependencies = { MarkerA.class, MarkerB.class })
interface ComponentC {
    MyClassA myClassA();

    MyClassB myClassB();
}

Why does Dagger2 allow passing interfaces not annotated with Component annotation to dependencies attribute?

@ronshapiro
Copy link

This is either Working As Intended and/or something that we could not reasonably detect.

At runtime, there's no way to detect that a component dependency instance is one that was generated by Dagger. Even if we could, there wouldn't be much meaning to that - a Dagger-generated component is just like any other implementation of that interface/abstract class. Restricting the exact implementation allowed could even cause issues with repackaging/shading. And if there's no reason the runtime type must be a component, why must the compile-time type be a component?

Often when we see "non-components" as dependencies, they are base types of what will eventually be a component. Something like this:

interface AppComponent {
  App app();
}

@Component(dependencies = AppComponent.class)
interface RequestComponent { ... }

@Component
interface EnglishAppComponent extends AppComponent {}

@Component
interface SpanishAppComponent extends AppComponent {}

@guliash
Copy link
Author

guliash commented Jul 17, 2018

I got it. Thank you for the quick response.

@guliash
Copy link
Author

guliash commented Jul 17, 2018

@ronshapiro, could you please explain one more thing?
Why do we have "depends on more than one scoped component" error? At first I thought it is needed to prevent creation of multiple instances of classes marked with Singleton annotation. But after your answer I can't find a reason for the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants