avaje-inject: Ideally avaje-inject-generator should not depend on avaje-inject
A lot of folks are not aware of this but you should almost never use the actual annotation classes in an annotation processor even your own. BTW I only know of couple libraries that generally do this correctly: MapStruct, JStachio (mine) and I believe Micronaut (so don’t feel bad). It is also probably why no one knows about Hickory (or the new MapStruct gemtools).
So why is it problematic? Well the annotation processor is not guaranteed to have classes loaded and if your annotation references other classes (e.g. has a Class<?>
parameter ) that are not yours you will have issues especially and I mean especially if you are dealing with modularized projects.
So why have you guys not run into issues? Well because both Maven and I think gradle as well will simply move whatever dependencies that are in <annotationProcessorPaths>
into the classpath during compilation. Otherwise all libraries that are referenced with requires
(static or not) in module-info
(and not in the annotationProcessorPaths) will be put in the module-path.
The above is one the reasons why <annotationProcessorPaths>
is required for modular projects but it is seriously limited and technically not correct either: https://issues.apache.org/jira/browse/MCOMPILER-391 and https://issues.apache.org/jira/browse/MCOMPILER-412
Otherwise if avaje-inject-generator does not have dependencies just having avaje-inject-generator on the classpath will work and you would not need to do <annotationProcessorPaths>
for modular projects and this is one of the big advantages to doing it the painful. BTW this is also why lots of annotation processors shade their deps but you can’t really do that for annotations.
So how do you access your own annotations without using them directly? You have to load the TypeElement.
Instead of Scope.class
you are going to pass a TypeElement. To get the TypeElement you can either get it from the call process function or just call Elements.getTypeElement
: https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/util/Elements.html#getTypeElement(java.lang.CharSequence)
Anyway that is easy and fine however it becomes a pain in the ass to get annotation parameters. That is where Hickory comes in (or mapstruct gemtools but you would have to shade it). https://javadoc.io/static/com.jolira/hickory/1.0.0/net/java/dev/hickory/prism/package-summary.html
Hickory is an annotation processor that makes what are called prisms which you can access your annotations as though you are accessing them directly.
Anyway I normally would not bother even bringing all this up as yeah there is a work around … manually register annotation processors…
But the project appears to not heavily dependent on its annotation core lib and is not a big change. In fact I could probably do a PR and do it myself if you are interested.
Furthermore it is technically the right way to do it and will prevent problems in the future as more folks embrace modularity.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 58 (7 by maintainers)
It’s good that we now have two modernized hickories.
Mine will work if someone wants to run the annotation processoron the modulepath.
And avaje’s fork will work on Java 8 and above (mine is compiled to 17).
So a massive thanks to both of you !! I think we’ve ended up with a really good result - love it !!
Cheers, Rob.
I can’t take any credit here. @SentryMan did all the work making the fork and then applying it to the AP’s. I’ve been the glorified second set of eyes and touch up guy.
Cool. As I see it, it wouldn’t matter if in some future setup the avaje-prisms AP actually ran as well as it would have nothing to process / there would be no code compiled with the prisms annotations on it in this case.