Indexed `provided` annotation breaks `build` goal (or app startup) in 2.14
See original GitHub issueDescribe the bug
While trying to upgrade from 2.13.3 to 2.14.0/1 I was greeted with a strange java.lang.ClassNotFoundException: lombok.NonNull
very early in the boot process of the app.
This is in a multi-module project that is working just fine with Quarkus 2.13.3 (and the “old” Jandex 1.2.3).
In a non-app module, a class is using lombok.NonNull
on a field alongside lombok.RequiredArgsConstructor
.
jandex-maven-plugin
is executed in the module to provide an index.
The lombok jar is a provided
dependency (as recommended generally).
See the reproducer further down.
Expected behavior
Should work as in 2.13
Actual behavior
Fails at app startup (with ECJ) or already when building the app via build
goal (with standard compiler).
How to Reproduce?
mvn clean verify
:
[INFO] --- quarkus-maven-plugin:2.14.1.Final:build (default) @ code-with-quarkus-app ---
[WARNING] [io.quarkus.arc.processor.BeanArchives] Failed to index lombok.NonNull: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD@65f470f8
[INFO] [io.quarkus.arc.processor.IndexClassLookupUtils] Class for name: lombok.NonNull was not found in Jandex index. Please ensure the class is part of the index.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for code-with-quarkus 1.0.0-SNAPSHOT:
[INFO]
[INFO] code-with-quarkus .................................. SUCCESS [ 0.027 s]
[INFO] code-with-quarkus-lib .............................. SUCCESS [ 0.924 s]
[INFO] code-with-quarkus-app .............................. FAILURE [ 1.511 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.968 s
[INFO] Finished at: 2022-11-22T23:13:14+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:2.14.1.Final:build (default) on project code-with-quarkus-app: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR] [error]: Build step io.quarkus.arc.deployment.ArcProcessor#generateResources threw an exception: java.lang.IllegalStateException: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Annotation class not available: @NonNull
[ERROR] at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:918)
[ERROR] at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
[ERROR] at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
[ERROR] at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR] at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR] Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Annotation class not available: @NonNull
[ERROR] at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
[ERROR] at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
[ERROR] at io.quarkus.arc.processor.BeanProcessor.generateResources(BeanProcessor.java:319)
[ERROR] at io.quarkus.arc.deployment.ArcProcessor.generateResources(ArcProcessor.java:570)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR] at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
[ERROR] ... 6 more
[ERROR] Caused by: java.lang.NullPointerException: Annotation class not available: @NonNull
[ERROR] at java.base/java.util.Objects.requireNonNull(Objects.java:233)
[ERROR] at io.quarkus.arc.processor.AnnotationLiteralProcessor.create(AnnotationLiteralProcessor.java:87)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.collectInjectionPointAnnotations(BeanGenerator.java:1937)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.wrapCurrentInjectionPoint(BeanGenerator.java:1837)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.initConstructor(BeanGenerator.java:704)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.createConstructor(BeanGenerator.java:614)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.generateClassBean(BeanGenerator.java:355)
[ERROR] at io.quarkus.arc.processor.BeanGenerator.generate(BeanGenerator.java:122)
[ERROR] at io.quarkus.arc.processor.BeanProcessor$4.call(BeanProcessor.java:258)
[ERROR] at io.quarkus.arc.processor.BeanProcessor$4.call(BeanProcessor.java:254)
[ERROR] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[ERROR] ... 5 more
mvn clean verify -Pquarkus-2.13.4
is fine though (switches from Quarkus 2.14.1 to 2.13.4 and jandex-plugin to the old coordinates and version)
Please note that this reproducer is not using ECJ (unlike my actual project), hence the error at build time, not boot time. If required I can provide a ECJ setup like in https://github.com/smallrye/jandex/issues/268. I actually started with an ECJ setup, stripped it down and was then surprised by the different behavior.
Output of uname -a
or ver
No response
Output of java -version
17.0.5
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.14.1
Build tool (ie. output of mvnw --version
or gradlew --version
)
No response
Additional information
I think it’s an issue in Jandex (cc @Ladicek), but I’m not entirely sure. Might also be related to Arc (cc @mkouba @manovotn )?
If I had to guess (wildly), I’d suppose that Jandex 3 is more strict about missing annotations.
Please note that there have been discussions about why lombok.NonNull
has CLASS
retention in the first place: https://github.com/projectlombok/lombok/issues/895
I do think the maintainer has a point though: https://github.com/projectlombok/lombok/issues/895#issuecomment-145653045
Issue Analytics
- State:
- Created 10 months ago
- Comments:17 (11 by maintainers)
Fix confirmed in 2.14.2! Thanks all, especially @Ladicek .
Okay, so what I’m doing is:
AnnotationLiteralProcessor
will still throw if the annotation class isnull
, and most callers don’t check that. That’s because most callers deal with qualifiers and interceptor bindings, and those must always exist. So if a qualifier class or an interceptor binding class is missing, we’ll still fail. There are 2 places that deal with arbitrary annotations on injection points, and those will just check if the annotation class exists or not.AnnotationLiteralProcessor
will additionally throw if the annotation is class-retained. Again, most callers deal with qualifiers and interceptor bindings, and those must always be runtime-retained. So if a qualifier or interceptor binding is class-retained, we’ll fail. I think that’s good. The same 2 places mentioned in previous item are modified to just skip class-retained annotations.WDYT?
EDIT: if you want to see the code, it’s here: https://github.com/Ladicek/quarkus/commits/filter-annotation-literals I want to run CI first in my fork before opening a PR.
That sounds sensible. I’ll see if I can come up with a better API.