I found an example with gradle and kapt … but I’m looking for a maven example or documentation.
Looking at kotlin-annotation-processing 1.0.0-beta-3595 it seems gradle specific. Looking at kotlin-maven-plugin … there is not similar support for annotation processing in maven.
Hmmm.
We don’t support kapt
for Maven yet. What is your use case?
My use case is using Kotlin to write JPA entity beans. The annotation processor generates “query beans” which are used to create type safe Ebean ORM queries ( http://ebean-orm.github.io/docs/query/typesafe#examples ).
What the annotation processor does is read the properties/fields of the (JPA entity) bean (including properties/fields from the inheritance hierarchy) and generate source for the “query beans”. This is a bit like JPA meta model generation.
For the maven/Java case (entity beans written in Java) I can use a standard java annotation processor which is great (automated).
For the maven/Kotlin case (entity beans written in Kotlin) right now I can workaround it by having a manual step … I run a program that reads the compiled bytecode using ASM (reads the fields/properties of the kotlin entity beans) and generates the “query beans” java source.
Ideally I could register a kapt like processor that automates the above manual step so that the query beans are generated automatically after a Kotlin compile. It gets told which kotlin classes were compiled (with @Entity or @MappedSuperclass annotations) and has the ability to reflect/read the properties/fields including inherited properties/fields and from this generate java source much like a normal javac annotation processor (and this all occurs prior to maven running the javac compile so the kotlin-maven-plugin is run in process-sources phase).
Note that I have an example project in github but I think I’ll move it (currently it is at avaje-ebeanorm-examples/e-kotlin-maven at master · ebean-orm-examples/avaje-ebeanorm-examples · GitHub).
Cheers, Rob.
Thanks. We’ll look into it at some point, but can’t say exactly when, sorry
No problem. I saw the Kotlin compiler plugin API so my next option is to look into that and see if that provides an approach. I have not had the time to look into that yet but that is my plan and hopefully I can do that in the next 2 weeks (and report back how I go with that).
Cheers, Rob.
It would be awesome to use all those APT based libraries we already have at our current java stack, but using the amazing Kotlin syntax.
abreslav
Do you think it would be too hard to compatibilize with default Java APT API? I mean, make kotlin-maven-plugin to call default APT to generate source codes?
Well, we can probably do the same as we do for Gradle: https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/kapt/kaptStubGeneratorUtils.kt
In essence, what it does is feeds Kotlin class-files to javac
as if they were sources.
It’s substantial work, though not something huge.
In practice it means that we can create a new goal at the kotlin-maven-plugin to generate stubs in order to javac
apply the APT as it does with ordinary java classes, right?
About these generated stub classes. Does gradle bundle it within the output jar? Once the Kotlin compiler generate a fully compatible .class
file, it may led to class duplication issues, right?
I’m just asking to understand exactly what the Gradle task does, so I can reproduce a similar a approach in a maven plugin.
I think these two blog posts may help:
- http://blog.jetbrains.com/kotlin/2015/05/kapt-annotation-processing-for-kotlin/
- Better Annotation Processing: Supporting Stubs in kapt | The Kotlin Blog
And the best way to understand what’s done in Gradle is read the code, IMO But feel free to ask more questions, we’ll be happy to explain the details
Hi @abreslav
I did investigate the Gradle code you point me out. I confess it took a while to understand the solution. Indeed, it was quite a simple solution, generating the APT stubs at the compile time.
I was thinking, wouldn’t it be easier if you manually call the javax.tools.JavaCompiler
after generate the .class
from the .kt
source? I just took a look at the .class
generated byte code and it kept the all annotations and method signatures needed by any ordinary Annotation Processor like Dagger.
I did this piece of code as a proof of concept. Basically, it used Fernflower to read the .class
and let the JavaCompiler
did its job. Here, you can find a maven project that uses this plugin. One of its dependencies exposes Java methods as RESTFul endpoints at compile time.
If you think it make sense, it could apply the same approach at the kotlin-maven-plugin. Maybe, as a secondary goal.
I would be happy to hear a honest your feedback about it. If you have a better approach, please let me know, okay?
Best regards
Hi,
Sorry for the delay, we’ll look into it soon!
If I am right, you are saying about reading annotations from the class files generated by the Kotlin compiler.
Actually, this is the way kapt works now. The APT wrappers generated in kaptStubGeneratorUtils.kt
is just the small part of it.
Annotation Processing API can read declarations from the class files directly, and there’s no need in Java decompiler. Furthermore, even if the decompiler (or any other stub generator) always produce the correct Java code, you would need to somehow exclude such source-stub files from the actual compilation stage, or remove the generated class files after the javac finishes. And, of course, generating such stubs is an extra work which affects build time.
Annotation Processing API can read declarations from the class files directly, and there’s no need in Java decompiler.
How can that be done? Is there some mechanism / library to fire annotation processors from reading .class files? If so that would be exactly what I’m after.
Thanks, Rob.
Hi, Is there any update / plan for maven APT processing?
Thanks, Rob.
Please feel free to upvote https://youtrack.jetbrains.com/issue/KT-14478