Dagger 2 - Component scoping compilation error - android

Simple scope annotation:
#Scope
#Retention(RUNTIME)
public #interface SimpleScope {
}
Simple component:
#SimpleScope
#Component
public interface SimpleComponent {
}
compiler error:
error: Scoping annotations are only allowed on concrete types and
#Provides methods

The compiler error is actually coming from Dagger 1 annotation processor. Specifically here: Dagger 1 ValidationProcessor. If the annotation processor sees that any interface is annotated with a javax.inject.Scope annotation, it reports an error. Even if the interface or scope are not used by Dagger 1 in any way.
We are currently migrating from Dagger 1 to Dagger 2, and hence both annotation processors are running on Gradle modules that use both Dagger 1 and Dagger 2.
One solution is to fully migrate each Gradle module, so that both annotation processors don't have to run on the same code. However, this is not always easy.
Our solution was to fork Dagger 1 and modify the ValidationProcessor to not fail if the interface is a Dagger 2 component.

Related

Why a class can't find #Named provider from a Hilt module?

I am migrating the application from Dagger2 to Hilt, and I started it from creating a single activity that uses Hilt
I wrote the inject annotation for one of the dependencies inside the activity
I have the provider method(it has a return type) in my HiltApplicationModule
configService is one of the dependencies provideRemoteConfig needs, so for that I also have a provider named method
Moreover, one of the dependencies that RemoteConfig also uses - it uses that same configService that we need to inject
When I run the build, I receive the error
#javax.inject.Named("config_service_merchant") com.example.configapp.ConfigService cannot be provided without an #Provides-annotated method and
public interface ApplicationComponent extends AndroidInjector {
^
#javax.inject.Named("config_service_merchant") com.example.configapp.ConfigService is injected at
At this point, I am confused why it can't find it if I have the method
My assumption that it tries to find it in Dagger2 modules and application components that I still have in the project, but I am not sure.
Why does configService's provider cannot be found to be injected in one of the classes(particularly AnalyticsConfig)?

Migrating to Hilt from Dagger2

I am trying to follow the Hilt migration guide here:
https://dagger.dev/hilt/migration-guide.html
And have annotated all my modules with:
#InstallIn(SingletonComponent::class)
However I am running into issues with my "Contributor" Modules for services, fragments and activities.
I have one module for each,
#Module
#InstallIn(SingletonComponent::class)
abstract class FragmentContributorModule {
#ContributesAndroidInjector
internal abstract fun contributeMyFragment(): MyFragment
}
#Module
#InstallIn(SingletonComponent::class)
abstract class ActivityContributorModule {
#ContributesAndroidInjector
internal abstract fun contributeMyActivity(): MyActivity
}
#Module
#InstallIn(SingletonComponent::class)
abstract class ServiceContributorModule {
#ContributesAndroidInjector
internal abstract fun contributeMyService(): MyService
}
During compile I am getting errors for each one of the "contribute" functions:
com.test.ActivityContributorModule_ContributeMyActivity$defaultsDebug is missing an #InstallIn annotation. If this was intentional, see https://dagger.dev/hilt/compiler-options#disable-install-in-check for how to disable this check.
I have also tried to use ServiceComponent::class, FragmentComponent::class and ActivityComponent::class for each Module with no luck. I am trying to migrate the project in pieces so I don't think I can remove these until everything is upgraded to Hilt.
Any ideas?
The answer is here:
Warning: Modules that are not annotated with #InstallIn are not used
by Hilt. Hilt by default raises an error when unannotated modules are
found, but this error can be disabled.
Was not 100% clear to me at first, but the contributor modules I have for services/fragments/activities are only used with Dagger, not Hilt. So if you are trying to migrate you project in pieces you can leave those module as is until you start to provide Hilt entry points for your services/fragments/activities. However if you do that, you will need to tell Hilt to ignore the error it throws for missing #InstallIn.
More info on how to disable that here:
https://dagger.dev/hilt/compiler-options.html#disable-install-in-check
By default, Hilt checks #Module classes for the #InstallIn annotation
and raises an error if it is missing. This is because if someone
accidentally forgets to put #InstallIn on a module, it could be very
hard to debug that Hilt isn’t picking it up.
This check can sometimes be overly broad though, especially if in the
middle of a migration. To turn off this check, this flag can be used:
-Adagger.hilt.disableModulesHaveInstallInCheck=true.
Alternatively, the check can be disabled at the individual module
level by annotating the module with #DisableInstallInCheck.

Creating Application scope as singleton in Kotlin

In Dagger2 while using java I create the application scope and use as singleton as below
#Scope
#Retention(RetentionPolicy.CLASS)
public #interface MyApplicationScope {
}
Question : Now how to write the similar code in Kotlin
What I tried:
#Scope
#Retention(AnnotationRetention.RUNTIME)
annotation class ApplicationScope
I don't get the option .CLASS
The Kotlin equivalent to Java's RetentionPolicy.CLASS is AnnotationRetention.BINARY. Both refer to annotations that need to be retained in the JAR or other compiler output file, but do not need to be available at runtime.

Dagger 2 using classes generated by another library

I have a homemade library that generates DataMapper classes.
They are generated with #Singleton and #Inject annotations to be able to inject them where i need them.
But where it doesn't work is when Dagger tries to create the dependency tree, this error shows :
:data:kaptGenerateStubsDebugKotlin
e: /Users/me/myproject/data/build/tmp/kapt3/stubs/debug/com/myproject/data/di/DataComponent.java:11: error: [Dagger/MissingBinding] error.NonExistentClass cannot be provided without an #Inject constructor or an #Provides-annotated method.
public abstract com.myproject.domain.repository.ContentRepository contentRepository();
^
error.NonExistentClass is injected at
com.myproject.data.repository.ContentDataRepository.<init>(…, myGeneratedDataMapper, …)
com.myproject.data.repository.ContentDataRepository is injected at
com.myproject.data.di.module.DataModule.contentRepository(contentDataRepository)
com.myproject.domain.repository.ContentRepository is provided at
com.myproject.data.di.DataComponent.contentRepository()
:data:kaptDebugKotlin
:data:kaptDebugKotlin FAILED
Involved classes are :
DataModule (module for dagger)
#Module
class DataModule {
#Provides
#Singleton
fun contentRepository(contentDataRepository: ContentDataRepository): ContentRepository = contentDataRepository
}
DataComponent (component for dagger):
#Singleton
#Component(modules = [DataModule::class])
interface DataComponent {
fun contentRepository(): ContentRepository
}
ContentDataRepository
#Singleton
class ContentDataRepository #Inject constructor(
private val myGeneratedDataMapper: MyGeneratedDataMapper
) : ContentRepository {
...
}
MyGeneratedDataMapper
#Singleton
class MyGeneratedDataMapper #Inject constructor() {
...
}
The thing is, if i disable kapt of dagger dependency in gradle.build, then build, then enable it, then build, it works.
If i do a clean + build, it doesn't work, same error.
I want to make it work in one row.
I don't know if you are using AS3.2 or AS3.3 with androidX artifacts or not but Maybe this is the case with you too.
so when i migrated to androidX artifacts in AS3.2 i got hit with bunch of NonExistentClass errors ends the build with
kaptGenerateStubsDebugKotlin
:data:kaptDebugKotlin
:data:kaptDebugKotlin
I finally found out that it has something to do with Dagger itself and degraded the version from 2.17 to 2.16 now the latest version of Dagger2 is 2.18 which i can't use due to this bug / feature [they forgot about].
Update:
i found the solution and it just came today so here is the issue tracker link:
https://issuetracker.google.com/issues/115738511
so the bug was not in the Dagger but it was with Jetifier and i totally ignored the fact that it was set enabled during migration
here's the solution i copied from the link:
Sorry jetifier beta01 was not binary compatible with alpha10.
We have published beta02 that should fix this issue.
Please try:
buildscript { dependencies {
classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02' } }
You're probably not going to like my answer but the order is kinda random.
Look at this thread for some more explaining and maybe some more guidance but, if you want to verify you are running first look at Gradle plugins and how to use them

Square Dagger error: class is exclusively members injected / cannot be scoped required

I get following error message from Dagger when compiling the module:
test.MyClass is exclusively members injected and therefore cannot be scoped required by test.MyModule for test.MyModule
Google is no help in this case.
I have a quite simple architecture: 1 module, all injected classes are listed in injects clause. I don't see anything what may cause a problem.
There error seems to be caused by not having an #Inject constructor.
In my case, I was using lombok constructor generation on the class. IE.
#RequiredArgsConstructor(onConstructor = #__({#Inject}))
public class MyClass {
private final AnotherClass anotherClass;
}
And changing to an explicit constructor resolved the problem.
I expect the failure is related to dagger running before the generated code is generated. (Similar to this question and the related issue.)

Categories

Resources