Problems with singletons when using component dependencies

JavaDagger 2

Java Problem Overview


I'm having a problem in understanding why the following code doesn't work.

I have following project structure:

@Component(modules = CCModule.class) 
public interface CComponent {
    XXX getXXX();
}

where

@Module
public class CCModule {

    @Provides @Singleton
    public XXX provide XXX(){
        return new XXX();
    }
}

and

@Component(dependencies = CComponent.class, modules = AAModule.class) 
public interface AComponent {
    YYY getYYY();
}

where

class YYY {
   @Inject
   public YYY(XXX xxx) {
       ...
   }
}

I initialize everything as:

CComponent c_component = Dagger_CComponent.builder().cCModule(new CCModule()).build();

AComponent a_component = Dagger_AComponent.builder()
        .cComponent(c_component)
        .aAModule(new AAModule())
        .build();

Once compilation takes place i get the following error:

> Error:(11, 1) error: > com.test.CComponent (unscoped) may not > reference scoped bindings: @Provides @Singleton > com.test.XXX > com.test.CCModule.provideXXX()

What I'm aiming for is to have one component inherit bindings from other components to have the same references to an objects (singletons).

Java Solutions


Solution 1 - Java

You should put @Singletonto CComponent class declaration.

@Singleton
@Component(modules = CCModule.class) 
public interface CComponent {
    XXX getXXX();
}

Explanation is in error message: CComponent is unscoped, @Singleton is a scope. Dagger 2 does not allow unscoped components to use modules with scoped bindings.
However, now you will get the following error:

AComponent (unscoped) cannot depend on scoped components:
@Component(dependencies = CComponent.class, modules = AModule.class)

Unscoped components cannot have scoped dependencies. So you need to make AComponent scoped. To do this create custom AScope annotation.

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface AScope {
}

And annotate with it AComponent:

@AScope
@Component(dependencies = CComponent.class, modules = AModule.class)
public interface AComponent {
}

These are new requirements appeared in latest snapshot release. It was discussed in corresponding issue and may still be changed.

Solution 2 - Java

Add

@Singleton
@Component(modules = {NameModule.class})
public interface NameComponent {

}

for the component because dagger2 don't allow to use unscoped components with scoped modules

Solution 3 - Java

Looks like a bug in the latest Dagger-2 release: https://github.com/google/dagger/issues/107

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCativailView Question on Stackoverflow
Solution 1 - JavaKirill BoyarshinovView Answer on Stackoverflow
Solution 2 - Javasonal balekaiView Answer on Stackoverflow
Solution 3 - JavaAlexander VasiljevView Answer on Stackoverflow