kapt: Annotation Processing for Kotlin

Andrey Breslav

This post is largely outdated.
Please refer to the kapt documentation
.

As there have been many requests to support Java Annotation Processing, we are working on it, and first results are ready for preview. This is the call for early feedback.

We are planning to release the initial support for JSR 269 Annotation Processing in M12, which is planned for the end of May. Meanwhile, the bulk of the work is already done, and you can test it by using the SNAPSHOT version of the Kotlin plugin for Gradle. The support is rather limited, but Dagger 2 works 🙂

Annotation Processing Basics

JSR 269 defines an API for a special kind of plugins for the Java compiler, annotation processors. Such a plugin can ask the compiler, roughly, “what code elements (classes, methods, fields) are annotated with @Foo?” The compiler returns a collection of objects that represent annotated elements. Then, the processor can inspect them and generate some new code that will be compiled during the same pass as the annotated code. The trick is that the generated code can be used by the hand-written code although it did not exist when the compiler started working.

To support Annotation Processing in a language other than Java, one has a few options:

One. Re-implement the JSR 269 APIs. This requires some work, but is not terribly hard. The problem is that it does not helped in a mixed project: in the end we need to process annotated element from both Java and Kotlin code, and only supporting JSR 269 in Kotlin is not that much of a gain.

Two. Generate Java sources from Kotlin sources and then feed them into the Java compiler that in turn runs the processors. Of course, it’s too hard to translate Kotlin to completely working Java code (translation of method bodies would be extremely painful), but all that’s really needed is just declarations. This is the way Groovy does it: by generating Java “stubs” from Groovy code and feeding them to the Java compiler. This would work for Kotlin too, but requires two runs of the compiler: first to generate stubs, and second to compile fully against generated code. Referring to classes generated by the processors is possible, but there will be issues in some cases (inferring property/function types from the right-hand-side expressions that use generated code, while generating stubs).

Three. Pretend that Kotlin binaries are Java sources. Normally, the Kotlin compiler runs first and the Java compiler sees the Kotlin code as binary .class files. Of course, all code elements, both source and binary, are represented uniformly inside the Java compiler. So instead of getting only annotated Java sources, the processor may also get annotated Kotlin binaries, it won’t notice the difference through the available API. Unfortunately, Javac won’t do that automatically, but we can plug in between the Java compiler and the annotation processor, find the binary elements ourselves and add them to the source elements normally returned by javac. A huge advantage is that this solution is rather easy to implement (involves a little bytecode generation, but we are kind of used to it:) ). There are a few important limitations, though: Kotlin code can not refer to the declarations generated by the processor and source-retained annotations are not visible through binaries. (Update: both limitations have been lifted later on.)

For now, we went for the option three under then name of kapt (Kotlin Annotation Processing). It looks like it enables the most important real-life use cases. We may support option two later, though.

Example: Using Dagger 2

kapt is supported by the Gradle plugin, to enable it, add

dependencies {
    ...
    compile 'com.google.dagger:dagger:2.0'
    kapt 'com.google.dagger:dagger-compiler:2.0'
    provided 'org.glassfish:javax.annotation:10.0-b28'

to your build script. Annotations will be picked up from both your Java and Kotlin code.

Since kapt is not released yet, it is only available from the SNAPSHOT version of Kotlin:

buildscript {
    repositories {
        ...
        maven {
            url 'http://oss.sonatype.org/content/repositories/snapshots'
        }
    }
    dependencies {
        ...
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT"
    }
}

Due to limitations mentioned above, the class(es) using code generated by Dagger have to be written in Java (normally, it is very little code):

import android.app.Application;

public abstract class BaseApplication extends Application {

    protected ApplicationComponent createApplicationComponent() {
        return DaggerApplicationComponent.builder()
                .androidModule(new AndroidModule(this)).build();
    } 
}

Everything else can be written in Kotlin. Here’s an example project demonstrating usage of Dagger: kotlin-dagger (you may need to enforce re-downloading of snapshot artifacts).

Feedback

We’d really appreciate if you tried kapt in your project and gave us feedback:

  • What frameworks did you try it with?
  • Did it work for you?
  • How much Java code did you have to write?
  • Any other issues?
Comments below can no longer be edited.

21 Responses to kapt: Annotation Processing for Kotlin

  1. Eddie Ringle says:

    May 22, 2015

    Building with 1.2.3 of the Android Gradle plugin fails. The kotlin-dagger sample uses 1.1.0.

    Error:

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring project ':app'.
    > Failed to notify project evaluation listener.
       > javaCompileTask
    
    * Try:
    Run with --info or --debug option to get more log output.
    
    * Exception is:
    org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':app'.
        at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:79)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:74)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:61)
        at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:487)
        at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:85)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:47)
        at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:129)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:50)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:27)
        at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40)
        at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
        at org.gradle.launcher.Main.doAction(Main.java:33)
        at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
        at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:33)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:130)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:48)
    Caused by: org.gradle.internal.event.ListenerNotificationException: Failed to notify project evaluation listener.
        at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:98)
        at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
        at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy12.afterEvaluate(Unknown Source)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:67)
        ... 33 more
    Caused by: java.lang.NoSuchFieldError: javaCompileTask
        at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.processVariantData(KotlinPlugin.kt:368)
        at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.access$processVariantData$0(KotlinPlugin.kt:291)
        at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin$apply$2.execute(KotlinPlugin.kt:343)
        at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin$apply$2.execute(KotlinPlugin.kt:291)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:113)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:102)
        at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:87)
        ... 37 more
    
    • Yan Zhulanow says:

      May 25, 2015

      Thank you for the feedback! I will investigate this issue.

  2. Даниил Водопьян says:

    May 22, 2015

    @Andrey, I am a little confused by your explanation of limitations for the third option. I guess I don’t know the compilation process well enough. What documentation did you use? Don’t know what to google for. Could you please give me to a starting point?

    • Andrey Breslav says:

      May 22, 2015

      JSR 269 API reference should be enough

  3. cypressious says:

    May 22, 2015

    This is great news! Will M12 also contain the possibility to annotate the setter method of delegated properties? This way we could inject vars delegated to notNull().

  4. Mickele Moriconi says:

    May 23, 2015

    Nice work guys, this is definitely the last barrier! 🙂

    So, I tried to use DBFlow (https://github.com/Raizlabs/DBFlow) but couldn’t make it work. I changed the Android Gradle plugin version as Eddie Ringle said previously.

    Error:


    FAILURE: Build failed with an exception.

    What went wrong:
    Execution failed for task ':app:compileDebugJava'.

    java.lang.NoSuchMethodError: kotlin.KotlinPackage.split$default(Ljava/lang/String;[CZII)Ljava/util/List;

    Try:
    Run with --debug option to get more log output.
    Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:compileDebugJava'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:305)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:80)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:51)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
    at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:33)
    at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:130)
    at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:48)
    Caused by: java.lang.RuntimeException: java.lang.NoSuchMethodError: kotlin.KotlinPackage.split$default(Ljava/lang/String;[CZII)Ljava/util/List;
    at com.sun.tools.javac.main.Main.compile(Main.java:553)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:42)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:35)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:97)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:50)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:36)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:34)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
    at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:158)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:138)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:92)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:235)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:222)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:200)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    ... 47 more
    Caused by: java.lang.NoSuchMethodError: kotlin.KotlinPackage.split$default(Ljava/lang/String;[CZII)Ljava/util/List;
    at org.jetbrains.kotlin.annotation.KotlinAnnotationProvider.readAnnotations(KotlinAnnotationProvider.kt:56)
    at org.jetbrains.kotlin.annotation.KotlinAnnotationProvider.access$readAnnotations$0(KotlinAnnotationProvider.kt:22)
    at org.jetbrains.kotlin.annotation.KotlinAnnotationProvider$annotatedKotlinElements$1.invoke(KotlinAnnotationProvider.kt:34)
    at org.jetbrains.kotlin.annotation.KotlinAnnotationProvider$annotatedKotlinElements$1.invoke(KotlinAnnotationProvider.kt:22)
    at kotlin.properties.LazyVal.get(Delegation.kt:169)
    at org.jetbrains.kotlin.annotation.KotlinAnnotationProvider.getAnnotatedKotlinElements(KotlinAnnotationProvider.kt)
    at org.jetbrains.kotlin.annotation.AnnotationProcessorWrapper.process(AnnotationProcessorWrapper.kt:94)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    ... 66 more

    BUILD FAILED

    I tried using both annotated Java and Kotlin classes.

    Hope it helps, thanks.

    • Yan Zhulanow says:

      May 25, 2015

      Can you please send a test project to yan.zhulanow [at] jetbrains.com?

      • Mickele Moriconi says:

        May 26, 2015

        Done. Also if anyone is interested, I created a repository on GitHub with the source: https://github.com/mickele/kotlin-poc

        The master branch is a Kotlin + Java (android-apt) that is compiling and working.
        The kapt branch is the pure Kotlin + kapt that I’m having some issues with.

  5. vh says:

    May 23, 2015

    Will this enable the use of “active annotations”, e.g. that i can annotate a field as a javafx property and it automatically generates a javafx property class with bindings (akin to Xtend?)

    • Yan Zhulanow says:

      May 25, 2015

      You can’t modify Kotlin classes using Annotation Processors, as Active Annotations do.

      • vh says:

        May 27, 2015

        Which I always found limiting. The data annotation in Kotlin is a prime example of what I’m talking. Just make this process available as an API

  6. Paul says:

    May 23, 2015

    What about QueryDSL support?

  7. Dale King says:

    May 26, 2015

    This will not support AndroidAnnotations project which generates subclasses of annotated classes that you need to reference from other code.

  8. David Leppik says:

    May 27, 2015

    Having just educated myself on what Dagger and Dagger 2 are, it seems to me that this is the right direction, but ultimately not far enough. My philosophy (and one which resonates well with Kotlin) is that boilerplate is a sign that the language is missing a feature. Dagger 2 writes DI boilerplate for you.

    This is too big a project for Kotlin 1.0, but there’s clearly a need for language features that do DI at compile time, so you don’t need a separate code generator like Dagger 2.

  9. ion says:

    June 9, 2015

    in kotlin-dagger example is used ‘kotlin-android’,

    tried to use with gradle ‘kotlin’ plugin,
    dependencies {
    compile ‘org.jetbrains.kotlin:kotlin-stdlib:0.12.213’,
    ‘com.google.dagger:dagger:2.0’,
    kapt ‘com.google.dagger:dagger-compiler:2.0’
    }

    it doesn’t understand ‘kapt’

    Is this android only feature ???

    • ion says:

      June 9, 2015

      sorry it was the ,

  10. Vitaliy says:

    July 5, 2015

    As I see from this example kotlin-dagger little java wrapper for DaggerApplicationComponent is not a problem at all.
    Unpleasant restriction is that you need to use next line everywhere
    (getApplication() as DemoApplication).component().inject(this)

    • Andrey Breslav says:

      July 14, 2015

      You can define a function in Kotlin that does it for you

  11. Martynas says:

    August 16, 2015

    Everything worked like charm. So far… I just couldn’t make it to work in tests.
    DaggerTestSomeComponent was not generated from TestSomeComponent : SomeComponent. I’ve tried various combinations. Including creating absolutely new component just in tests. Still nothing. Is there any workaround or could I provide some other details?

  12. yanex says:

    October 19, 2015

    Please try to add a test kapt dependency:

    kaptTest “groupId:artifactId:version”.