I personally like the Idea of Micronaut doing much of its work at compile-time by annotation processors.
The short time I played with Micronaut and analyzed some of the generated build artefacts, I discovered several automatically generated class files in the output folders. If I understand correctly these are generated by the micronaut annotation processor.
However, my experience in projects with popular annotation processors like MapStruct, Immutables or AutoValue has always been that they will generate simple Java source files and not binary class files. To me this seems like the better solutation as these can be easily discovered and debugged by IDEs and also I as a developer can better understand what the generated code really is doing.
It would be great if the Micronaut annotation processor could generate source files instead of binary class files.
Or are there some technical limitations preventing this?
We generate binary code because we can better optimise the byte code via ASM and really this is not code as a developer you should be modifying, altering or toying with. By using byte code as well we end up with much shorter stack traces which actually results in a easier to debug solution.
In addition, the libraries for generating source code are also unwieldy and code generation leads to having yet another set of artefacts (source files) to manage and doesn't play well with Micronaut's support for multiple languages (Kotlin, Java and Groovy). We would start getting folks wanting the source code generated in Kotlin or Groovy instead of Java, which is simply not practical.
Maintaining both generating source code and generated byte code solution is not realistic, so we won't be fixing this, but thanks for the feedback.
Throwing my thrippence worth ... having the source code _available_ with things like Hibernate has proven _essential_ in past adventures.
Might there be an option to generate sources _along-side_ the binary Class file? I take the point about being better able to control what happens with a .class file. Just a thought.
I am in awe (in a good way) of how this framework uses ASM to generate code from annotation processing.
My only issue is that its pretty hard to figure out what exactly is going on. This isn't like Spring using Reflection, or another APT project where you can investigate the code. It's almost at the magic level of AspectJ but even that is a well defined language and library.
I took a glance at the ASM generation and its pretty incredible. You guys are working with 3 or 4 code abstractions: javax.lang.model.**, ASM, and java.lang.reflect for some edge case. Two of those libraries uses visitor patterns along with your own visitor patters. Consequently it makes it pretty difficult to figure out whats going on.
For example I can't tell if you are generating new code or modifying the existing classes. I can't tell if you are loading compiled classes or relying on the information from the annotation processor. I assume you just generate code and not modify.
Anyway it would be great if there was some more documentation on how it all works particularly as this is pretty much a critical component. I'm not sure I'm comfortable not knowing how it works and thus afraid to blindly use the library.
Thanks for the feedback maybe it makes sense to put together some architecture docs. Feel free to raise a separate issue for that. Note that we don鈥檛 modify user byte code ever
Note that we don鈥檛 modify user byte code ever
Yes I did read that in the doc btw but I couldn't figure out how you discovered the beans w/o code modification.
But I finally figured it out and its through the generated resource:
io.micronaut.inject.BeanDefinitionReference
For some reason I kept missing it with unzip -l some.jar.
Now it makes a lot more sense. You basically do what Spring does but generate the entire meta model as synthetic classes (aka BeanDefinitions) including a class for each executable method and annotations.
Since I know what spring does I have a pretty good idea how it works now.
I guess if one wanted to make their own annotations there is probably a service loader that the annotation processor can pick up right? Is that the annotation mapper stuff.
Anyway I think just a couple more tid bits of how it works would make it clear and perhaps I can make some recommendations once I wrap my head around the framework some more. Perhaps through custom annotations as mentioned earlier?
(sorry for the edits).
Most helpful comment
Thanks for the feedback maybe it makes sense to put together some architecture docs. Feel free to raise a separate issue for that. Note that we don鈥檛 modify user byte code ever