0

I've come across a scenario where even though I hadn't explicitly included a module (via either @Module(includes = { .. } ) or @Component(modules = { .. })), dagger is able to construct all the classes just fine.

To make things more clear, here's the example Maven project I created:

src/
├── main
│   ├── java
│   │   └── org
│   │       └── daggertest
│   │           ├── Main.java
│   │           ├── persistence
│   │           │   ├── di
│   │           │   │   └── PersistenceModule.java
│   │           │   └── PersistenceManager.java
│   │           ├── ui
│   │           │   ├── AppUI.java
│   │           │   └── di
│   │           │       └── UIComponent.java
│   │           └── util
│   │               ├── di
│   │               │   └── UtilModule.java
│   │               └── SystemUtil.java
│   └── resources
└── test
    └── java

There is a Main class and three packages (persistence, ui, util). There is a corresponding module for persistence and util. And a component for ui.

Let's start from the bottom. The UtilModule simply provides SystemUtil:

@Module
public class UtilModule {

    @Provides
    public SystemUtil providesSystemUtil() {
        return new SystemUtil();
    }
}  

Pretty straightforward. Nothing going on here. As requested in the comments, here is how SystemUtil looks:

public class SystemUtil {

    public Path getSomeFile(String fileName) {
        return Path.of(fileName);
    }
}

Then, in the persistence package, PersistanceManager injects SystemUtil. So PersistenceModule provides PersistenceManager like so:

@Module
public class PersistenceModule {

    @Provides
    public PersistenceManager providesPersistenceManager(SystemUtil systemUtil) {
        return new PersistenceManager(systemUtil);
    }
}  
  1. Even though PersistenceModule doesn't explicitly include the module (by doing @Module(includes = { UtilModule.class })), this works fine. Why?

Then, in the ui package, AppUI injects both PersistenceManager and SystemUtil. And I wrote UIComponent like so:

@Component(modules = { UtilModule.class })
public interface UIComponent {

    AppUI buildAppUI();
}  
  1. I only explicitly included the UtilModule. But it was still able to inject PersistenceManager even though I didn't specify the PersistenceModule. How is this able to work? Interestingly, if I don't include the UtilModule here, it fails.

My guess is that I have a misunderstanding of how the modules/components are able to isolate from each other.

  1. My expectation was that if it wasn't explicitly included in the Component or Module annotation, it would fail compilation. Is this not true? Is it possible to enforce this?
halfer
  • 19,824
  • 17
  • 99
  • 186
gjvatsalya
  • 1,129
  • 13
  • 29
  • Could you include a simplified version of `SystemUtil`? I'm guessing that you sprinkled `@Inject` everywhere... – David Medenjak Oct 26 '20 at 10:27
  • @DavidMedenjak I have edited in the entirety of SystemUtil in the post. Since this is just a test project, there's nothing going on in that class. It's a simple class with no dependencies. The only places where I have `@Inject` is in PersistenceManager and AppUI. – gjvatsalya Oct 27 '20 at 05:13
  • Your example is clearly missing _something_. If you don't use constructor injection and don't provide the object somehow (module, parent component, component dependency, component factory/builder) then Dagger will complain with _cannot be provided..._ I'm not sure what `AppUI` is, but assuming that everything else is as stated I'd guess `AppUI` only requests `SystemUtil`, which will be provided from the module you added. And that you don't use `PersistenceManager` which is why you don't need the module, either. – David Medenjak Oct 27 '20 at 17:20
  • @DavidMedenjak `AppUI` injects both PersistenceManager and SystemUtil. It's possible I'm missing something. As such, I've put up my code on github: https://github.com/jaygazula27/daggertest. It's a simple maven project with only a dagger dependency. So you should be able to run `mvn clean package` as long as you have Maven and Java installed. – gjvatsalya Oct 27 '20 at 21:37
  • @DavidMedenjak And as you can see here: https://github.com/jaygazula27/daggertest/blob/master/src/main/java/org/daggertest/ui/AppUI.java. I have both PersistenceManager and SystemUtil injected. – gjvatsalya Oct 27 '20 at 21:37
  • You have an [`@Inject` on the constructor](https://github.com/jaygazula27/daggertest/blob/61fae5732f280705fce1062a9edcfb1c7e99052a/src/main/java/org/daggertest/persistence/PersistenceManager.java#L12), thus it's using [constructor injection](https://stackoverflow.com/a/50270376/1837367) – David Medenjak Oct 27 '20 at 22:10
  • @DavidMedenjak Ah, I didn't realize constructor injection would make dagger just create the objects itself would having to manually provide it. Thanks for that information. – gjvatsalya Oct 29 '20 at 02:37

0 Answers0