Dagger and Kotlin. Dagger doesn't generate component classes - kotlin

I'm new with kotlin and Dagger. I have a little problem that I do not how to solve and I don't find a solution.
So this is what I have:
#Module
class AppModule (app: Application) {
private var application: Application;
init {
this.application = app;
}
#Provides fun provideApplication(): Application? {
return application;
}
#Provides fun provideResources(): Resources? {
return application.resources;
}
}
#Singleton
#Component(modules = arrayOf(AppModule::class))
interface AppComponent: AppComponentBase {
public class Initializer {
private constructor(){}
companion object {
fun Init(app: Application): AppComponent? {
return DaggerAppComponent.builder().appModule(AppModule(app)).build()
}
}
}
}
AppComponentBase: This interface contain all the methods needed by this component.
Now, the problem is that this DaggerAppComponent class is not generated by Dagger if I do this DaggerAppComponent.builder().appModule(AppModule(app)).build() invocation within the companion object.
If a invoke the same line any were by the companion object dagger generate de class without any problem.
An other thing I did look for a solution was create an other different class with the same structure, and importe the DaggerAppComponent as internal object, and I the same result happened.
I don't what to have the initialization of the component outside. So, there any other alternative solution, or what am I doing wrong?.

You need to have the kapt processor in build.gradle:
kapt {
generateStubs = true
}
dependencies {
...
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile 'com.google.dagger:dagger:2.0.2'
kapt 'com.google.dagger:dagger-compiler:2.0.2'
...
}
This extension will generate the code for dagger.
Additionally, for newer gradle versions, you can also apply the plugin in your build.gradle:
apply plugin: 'kotlin-kapt'
dependencies {
...
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile 'com.google.dagger:dagger:2.0.2'
kapt 'com.google.dagger:dagger-compiler:2.0.2'
...
}
You can check this project for reference

I don't know when this change happened, but on 1.1.2 of the Kotlin gradle plugin you replace this (in your module's build.gradle):
kapt {
generateStubs = true
}
with this:
apply plugin: 'kotlin-kapt'
and then make sure to replace dependencies that use annotationProcessor with kapt.
For example, the old way would be to use:
annotationProcessor (
'some.library:one:1.0'
...
'some.library.n:n.0'
)
and now you use:
kapt (
'some.library:one:1.0'
...
'some.library.n:n.0'
)

UPDATE FOR KOTLIN 1.1.4
generateStubs does not work anymore. Feel free to make a build with the latest Kotlin and it would tell you in the Messages section of Android Studio that it is not necessary anymore. Here's an up-to-date list of dependencies for Dagger2 for Android and Kotlin
apply plugin: 'kotlin-kapt'
//...
// Other Gradle stuff
//...
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.4-3"
compile 'com.google.dagger:dagger-android:2.12'
kapt 'com.google.dagger:dagger-android-processor:2.12'
compileOnly 'com.google.dagger:dagger:2.12'
kapt 'com.google.dagger:dagger-compiler:2.12'
}

This issue can be fixed with the bellow change which is different from original answer
Following will also work well to fix this issue
with plugins
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
and dependencies
implementation "com.google.dagger:dagger:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
For reference check out this Gist

Use these dependencies if you are using kotlin as the primary language for android application development
// Dagger dependencies
def dagger_version = "2.44"
implementation "com.google.dagger:dagger:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version" // if you use the support libraries
kapt "com.google.dagger:dagger-android-processor:$dagger_version"

My case must be some exclusion rule in Dagger's implementation
com.mycompany.native -> Dagger doesn't generate code
com.mycompany.other -> Dagger generates code
I wasted quite some time on this :-( I hope it helps someone else!

Sorry, I didn’t create a new issue, but decided to answer under similar questions, because maybe someone find it useful!
I faced to ridiculous issue! «Make Project» do not generate dagger files. They are generated while preparing run your App! But I was trying to solve problem for hours and didn't think of simple trying to click Run..)))
So, maybe you faced to the same problem:
Neither «Sync Project with Gradle» nor «Clean» and «Build Project» help generate dagger files.
-> Then just Run your App!
After the first Run App my Dagger started generated files if I click Make Project.

If u have problem withe DaggerComponent, You should add
apply plugin: 'kotlin-kapt'
kapt {
generateStubs = true
}
to build.gradleit will generate kotlin code for dagger 2 otherwise project will only build on Rebuild

Related

Configure Kotlin extension for Gradle subprojects

I'm setting up a multi-module Gradle project based on Kotlin for the JVM. Since the root project does not contain any code, the Kotlin plugin should only be applied to subprojects.
build.gradle.kts (root project)
plugins {
kotlin("jvm") version "1.6.20" apply false
}
subprojects {
apply(plugin = "kotlin")
group = "com.example"
repositories {
mavenCentral()
}
dependencies {}
kotlin {
jvmToolchain {
check(this is JavaToolchainSpec)
languageVersion.set(JavaLanguageVersion.of(11))
}
}
}
Trying to set a toolchain causes the build to fail at the kotlin {...} extension:
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun DependencyHandler.kotlin(module: String, version: String? = ...): Any defined in org.gradle.kotlin.dsl
public fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec defined in org.gradle.kotlin.dsl
It works fine if I copy the extension definition to each subproject build script, but why isn't it available in the main script?
This is one of my favourite things to fix in Gradle, and really shows off the flexibility that's possible (as well as demonstrating why Gradle can be complicated!)
First I'll give a bit of background info on the subprojects {} DSL, then I'll show how to fix your script, and finally I'll show the best way to share build logic with buildSrc convention plugins. (Even though it's last, I really recommend using buildSrc!)
Composition vs Inheritance
Using allprojects {} and subprojects {} is really common, I see it a lot. It's more similar to how Maven works, where all the configuration is defined in a 'parent' build file. However it's not recommended by Gradle.
[A], discouraged, way to share build logic between subproject is cross project configuration via the subprojects {} and allprojects {} DSL constructs.
Gradle Docs: Sharing Build Logic between Subprojects
(It's probably common because it's easy to understand - it makes Gradle work more like Maven, so each project inherits from one parent. But Gradle is designed for composition. Further reading: Composition over inheritance: Gradle vs Maven)
Quick fix: 'Unresolved reference'
The error you're seeing is basically because you haven't applied the Kotlin plugin.
plugins {
kotlin("jvm") version "1.6.20" apply false // <- Kotlin DSL won't be loaded
}
The kotlin { } configuration block is a very helpful extension function that is loaded when the Kotlin plugin is applied. Here's what it looks like:
/**
* Configures the [kotlin][org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension] extension.
*/
fun org.gradle.api.Project.`kotlin`(configure: Action<org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension>): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("kotlin", configure)
// (note: this is generated code)
So if we don't have the extension function, we can just call configure directly, and thus configure the Kotlin extension.
subprojects {
// this is the traditional Gradle way of configuring extensions,
// and what the `kotlin { }` helper function will call.
configure<org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension> {
jvmToolchain {
check(this is JavaToolchainSpec)
languageVersion.set(JavaLanguageVersion.of(11))
}
}
// without the Kotlin Gradle plugin, this helper function isn't available
// kotlin {
// jvmToolchain {
// check(this is JavaToolchainSpec)
// languageVersion.set(JavaLanguageVersion.of(11))
// }
// }
}
However, even though this works, using subprojects {} has problems. There's a better way...
buildSrc and Convention Plugins
buildSrc is, basically, a standalone Gradle project, the output of which we can use in the main project's build scripts. So we can write our own custom Gradle plugins, defining conventions, which we can selectively apply to any subproject in the 'main' build.
(This is the key difference between Gradle and Maven. In Gradle, a subproject can be configured by any number of plugins. In Maven, there's only one parent. Composition vs Inheritance!)
The Gradle docs have a full guide on setting up convention plugins, so only I'll briefly summarise the solution here.
1. Set up ./buildSrc
Create a directory named buildSrc in your project root.
Because buildSrc is a standalone project, create a ./buildSrc/build.gradle.kts and ./buildSrc/settings.gradle.kts files, like usual for a project.
In ./buildSrc/build.gradle.kts,
apply the kotlin-dsl plugin
add dependencies on Gradle plugins that you want to use anywhere in your project
// ./buildSrc/build.gradle.kts
plugins {
`kotlin-dsl` // this will create our Gradle convention plugins
// don't add the Kotlin JVM plugin
// kotlin("jvm") version embeddedKotlinVersion
// Why? It's a long story, but Gradle uses an embedded version of Kotlin,
// (which is provided by the `kotlin-dsl` plugin)
// which means importing an external version _might_ cause issues
// It's annoying but not important. The Kotlin plugin version below,
// in dependencies { }, will be used for building our 'main' project.
// https://github.com/gradle/gradle/issues/16345
}
val kotlinVersion = "1.6.20"
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
Note that I've used the Maven repository coordinates for the Kotlin Gradle plugin, not the plugin ID!
You can also add other dependencies into ./buildSrc/build.gradle.kts if you like. If you wanted to parse JSON in a build script, then add a dependency on a JSON parser, like kotlinx-serialization.
2. Create a convention plugin
Create your Kotlin JVM convention that you can apply to any Kotlin JVM subproject.
// ./buildSrc/src/main/kotlin/my/project/convention/kotlin-jvm.gradle.kts
package my.project.convention
plugins {
kotlin("jvm") // don't include a version - that's provided by ./buildSrc/build.gradle.kts
}
dependencies {
// you can define default dependencies, if desired
// testImplementation(kotlin("test"))
}
kotlin {
jvmToolchain {
check(this is JavaToolchainSpec)
languageVersion.set(JavaLanguageVersion.of(11))
}
}
}
Don't forget to add the package declaration! I've forgotten it a few times, and it causes errors that are hard to figure out.
3. Applying the convention plugin
Just like how Gradle plugins have IDs, so do our convention plugins. It's the package name + the bit before .gradle.kts. So in our case the ID is my.project.convention.kotlin-jvm
We can apply this like a regular Gradle plugin...
// ./subprojects/my-project/build.gradle.kts
plugins {
id("my.project.convention.kotlin-jvm")
}
(Convention plugins can also import other convention plugins, using id("..."))
Also, since we're using Kotlin, there's an even nicer way. You know how there are included Gradle plugins, like java and java-library. We can import our convention plugins the same way!
// ./subprojects/my-project/build.gradle.kts
plugins {
// id("my.project.convention.kotlin-jvm")
my.project.convention.`kotlin-jvm` // this works just like id("...") does
}
Note the backticks around the plugin ID - they're needed because of the hyphen.
(caveat: this non-id("...") way doesn't work inside buildSrc, only in the main project)
Result
Now the root ./build.gradle.kts can be kept really clean and tidy - it only needs to define the group and version of the project.
Because we're using convention plugins and not blanket subprojects, each subproject can be specialised and only import convention plugins that it needs, without repetition.
Site note: sharing repositories between buildSrc and the main project
Usually you want to share repositories between buildSrc and the main project. Because Gradle plugins are not specifically for projects, we can write a plugin for anything, including settings.gradle.kts!
What I do is create a file with all the repositories I want to use...
// ./buildSrc/repositories.settings.gradle.kts
#Suppress("UnstableApiUsage") // centralised repository definitions are incubating
dependencyResolutionManagement {
repositories {
mavenCentral()
jitpack()
gradlePluginPortal()
}
pluginManagement {
repositories {
jitpack()
gradlePluginPortal()
mavenCentral()
}
}
}
fun RepositoryHandler.jitpack() {
maven("https://jitpack.io")
}
(the name, repositories.settings.gradle.kts, isn't important - but naming it *.settings.gradle.kts should mean IntelliJ provides suggestions, however this is bugged at the moment.)
I can then import this as a plugin in the other settings.gradle.kts files, just like how you were applying the Kotlin JVM plugin to subprojects.
// ./buildSrc/settings.gradle.kts
apply(from = "./repositories.settings.gradle.kts")
// ./settings.gradle.kts
apply(from = "./buildSrc/repositories.settings.gradle.kts")

Kotlin serialization plugin does not generate serializers in Gradle project

I'm trying to use the Kotlinx Serialization libraries and the associated Gradle plugin. It's supposed to generate serializers for when when I annotate a class with #Serializable, like this:
#Serializable
data class Message(val version: String)
// (...)
Json.encodeToString(Message("1.0"))
It does not work, and the annotation is highlighted with:
kotlinx.serialization compiler plugin is not applied to the module, so
this annotation would not be processed. Make sure that you've setup
your buildscript correctly and re-import project.
As expected, the code does not compile as I'm expecting to use the Serializers further down the line, with the error:
Type mismatch: inferred type is Message but
SerializationStrategy<TypeVariable(T)> was expected
Here is my app-level build.gradle:
plugins {
id "java"
id 'org.jetbrains.kotlin.jvm' version '1.6.10'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.10'
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
dependencies {
implementation "com.amazonaws:aws-lambda-java-core:$lambda_runtime_version"
implementation "software.amazon.awssdk:dynamodb-enhanced:$aws_sdk_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialization_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
task fatJar(type: Jar) {
archiveClassifier = 'lambdaCode'
duplicatesStrategy = DuplicatesStrategy.WARN
from sourceSets.main.output
dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}
}
I'm using Gradle 7.3.3, and see all this in IntelliJ. I tried launching gradle build from the command line, with similar results, so the IDE does not seem to blame.
I read a lot of similar questions but I could not find an answer that worked for me. Can anyone shed some light on my situation?

Generate kotlin classes from xsd

There is an xsd schema. It is necessary to generate Kotlin-classes according to the xsd description. How can I do this? Using the code below, I can get java classes. But I need kotlin classes
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
// Apply the application plugin to add support for building a CLI application.
id 'application'
/* Generate Java code from XSD */
id 'org.unbroken-dome.xjc' version '1.4.3'
}
group 'org.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
xjc {
includeInMainCompilation = false
}
xjcGenerate {
source = fileTree('src/main/schema') { include '*.xsd' }
bindingFiles = fileTree('src/main/jaxb') { include '*.xjb' }
catalogs = fileTree('src/main/catalog') { include '*.cat' }
}
sourceSets {
main { java { srcDir xjcGenerate.outputDirectory } }
}
compileKotlin {
dependsOn xjcGenerate
}
/* END: Make xjcGenerate work with Kotlin */
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
google()
}
dependencies {
/* Add JAXB dependencies for Java 11 */
implementation 'javax.xml.bind:jaxb-api:2.3.1'
// Use the Kotlin JDK 8 standard library.
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
// Use the Kotlin test library.
testImplementation 'org.jetbrains.kotlin:kotlin-test'
// Use the Kotlin JUnit integration.
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
// Define the main class for the application.
mainClassName = 'ru.goryacms.AppKt'
I've tried https://github.com/reaster/schema-gen. It generates Kotlin data classes with annotations, but it has bugs so that the generated code does not compile, however this is easy to fix. In my case I also had to fix many annotations and some property names. Still much better than manually writing code.
You can try https://github.com/SixRQ/KAXB - Kotlin based class generator to generate native Kotlin classes from an XML Schema:
This project is used to generate native Kotlin classes from an xsd schema, similar to the JAXB tool for Java. The project will include a plugin for gradle and Intellij IDEA. ...
Once the archive has been extracted run the
bin/kaxb --P <destination package> --S <schema file> --T <target directory>

Can I write gradle buildSrc in Kotlin?

I'd like to write my Gradle buildSrc in Kotlin instead of Java, since everything else is Kotlin too.
I've tried .kt files in buildSrc/src/main/kotlin and in buildSrc/src/main/java, but neither will be compiled. IntelliJ does recognize them at least when I put them in /java, but they are not found when running Gradle tasks.
So, how do I make Gradle look at Kotlin build sources?
buildSrcis treated as an included build, and you can use any supported language inside this project, as long as you apply the needed plugins.
Following setup should work :
buildSrc/build.gradle
plugins {
id("org.jetbrains.kotlin.jvm") version "1.3.72"
}
repositories {
mavenCentral()
}
custom task:
buildSrc/src/main/kotlin/tasks/MyKtTask.kt
package tasks
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
open class MyKtTask : DefaultTask() {
#TaskAction
fun execute() {
println("kotlin tasks executed")
}
}
Using the custom task:
build.gradle
task "testKt" (type: tasks.MyKtTask){
doLast{
// do something
}
}

Kotlin Foo::class.java "Unresolved Reference: Java" error

I am trying to convert my Java code of HomePage.class to Kotlin. I am following the instructions on Kotlin.org:
getClass()
To retrieve the type information from an object, we use the javaClass
extension property.
val fooClass = foo.javaClass
Instead of Java’s Foo.class use
Foo::class.java.
val fooClass = Foo::class.java
I have a class called HomePage that extends AppCompatActivity (in Android). I am using Android Studio. I tried doing HomePage::class.java and it has an error: Unresolved reference: java
How do I get this to work?
The issue is most likely that you forgot to depend on the reflection libraries which were needed for the reflective functions of Kotlin.
On the Java platform, the runtime component required for using the
reflection features is distributed as a separate JAR file
(kotlin-reflect.jar). This is done to reduce the required size of the
runtime library for applications that do not use reflection features.
If you do use reflection, please make sure that the .jar file is added
to the classpath of your project.
Source
It turns out, I was using an older version of Kotlin, and it wasn't configured correctly. I edited the gradle file to include the latest beta version, and selected the option that configures Kotlin, and it works now.
In gradle:
buildscript {
ext.kotlin_version = '1.0.0-beta-3594'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
}
}
...
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
I Put in the beginning of Gradle (Module app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
and
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
or
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
in the dependencies section
In the build.gradle (Project)
buildscript {
ext.kotlin_version = '1.2.0'
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
For easy reference, here are the reflection dependencies when using Gradle:
Reflection libraries from the docs for Gradle in your build.gradle
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
compile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"
}
Reflection libraries syntax for Kotlin Script Gradle DSL in your build.gradle.kts
dependencies {
compile(kotlin("stdlib"))
compile(kotlin("reflect"))
compile(kotlin("test"))
compile(kotlin("test-junit"))
}
In build.gradle (app) I had:
implementation 'androidx.core:core-ktx:1.6.0'
And I replaced it by
implementation 'androidx.core:core-ktx:1.5.0'
And it worked!
The core version also killed some of y functions like: forEach
I used
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
Instead of
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
i use this
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
invalided cache & restart android studio!works fine!!
This happened to me after updating Android Studio and the Kotlin plugin, which required migration to a newer version of Kotlin. After configuring everything correctly, the error still persisted. Deleting .idea folder and reloading did not help, but good old File -> Invalidate Caches / Restart did the trick for me.
I copied the class from other project and forgot to change the class package name.
when I changed, it fixed
I saw this in AndroidStudio with Kotlin 1.2.71 and none of the above fixed it for me.
What sadly hilariously worked for me was closing the project, telling AndroidStudio to forget about the project and re-opening from the folder. Presto, no unresolved reference. Weird, I know.
In my case reducing version of kotlin fixed the issue
Change
ext.kotlin_version = '1.3.21'
To
ext.kotlin_version = '1.3.11'
Add this line in your Module build gradle
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
In Project build gradle:
buildscript {
ext.kotlin_version = '1.3.21'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.google.gms:google-services:4.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
I encountered this error when i downloaded and run android studio canary(artic fox). Since then my android studio(normal one) was giving this error i applied all the solutions given above but nothing worked . So i completely uninstalled the android studio and reinstalled the latest one (this was the only option left)