Originally posted by **ethanhere** February 21, 2024
Micronaut 4 annotation processor NullPointerException
We have an application based on Micronaut 3. It builds and runs fun. Recent we upgrade it with micronaut 4 and we got java.lang.NullPointerException when compiling the project. The maven build message is:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.12.1:compile (default-compile) on project service-idm-dao-aws: Compilation failure
[ERROR] java.lang.NullPointerException: Cannot invoke "javax.lang.model.element.TypeElement.getKind()" because "type" is null
[ERROR] at io.micronaut.annotation.processing.visitor.JavaElementFactory.newSourceClassElement(JavaElementFactory.java:92)
[ERROR] at io.micronaut.annotation.processing.TypeElementVisitorProcessor.lambda$process$6(TypeElementVisitorProcessor.java:255)
[ERROR] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
[ERROR] at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
[ERROR] at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
[ERROR] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
[ERROR] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
[ERROR] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
[ERROR] at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
[ERROR] at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
[ERROR] at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
[ERROR] at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
[ERROR] at io.micronaut.annotation.processing.TypeElementVisitorProcessor.process(TypeElementVisitorProcessor.java:256)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1021)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:937)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1265)
[ERROR] at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1380)
[ERROR] at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1272)
[ERROR] at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
[ERROR] at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319)
[ERROR] at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178)
[ERROR] at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:64)
[ERROR] at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:50)
I found a workaround to get the project built by delete an @Facotory annotated class:
"
package factories;
import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.AWSKMSClientBuilder;
import io.micronaut.context.annotation.Factory;
import jakarta.inject.Singleton;
@Factory
public class AmazonKmsFactory {
@Singleton
public AWSKMS kms() {
return AWSKMSClientBuilder.standard().build();
}
}
"
After analyzing https://github.com/micronaut-projects/micronaut-core/blob/e3f5fdb2726af5fdcab6906ad0db5165cbbb2a24/inject-java/src/main/java/io/micronaut/annotation/processing/TypeElementVisitorProcessor.java#L255 around line 255, I believe there is a bug here:
The stack trace I quoted says at io.micronaut.annotation.processing.TypeElementVisitorProcessor.lambda$process$6(TypeElementVisitorProcessor.java:255), it calls JavaElementFactory.newSourceClassElement and within newSourceClassElement method, NullPointerException was thrown.
In https://github.com/micronaut-projects/micronaut-core/blob/e3f5fdb2726af5fdcab6906ad0db5165cbbb2a24/inject-java/src/main/java/io/micronaut/annotation/processing/visitor/JavaElementFactory.java#L92 line 92, NPE was thrown because parameter type was null.
parameter type was passed from TypeElementVisitorProcessor.java:255 as typeElement
if (!elements.isEmpty()) {
JavaElementFactory elementFactory = javaVisitorContext.getElementFactory();
JavaElementAnnotationMetadataFactory elementAnnotationMetadataFactory = javaVisitorContext.getElementAnnotationMetadataFactory();
// The visitor X with a higher priority should process elements of A before
// the visitor Y which is processing elements of B but also using elements A
// Micronaut Data use-case: EntityMapper with a higher priority needs to process entities first
// before RepositoryMapper is going to process repositories and read entities
List javaClassElements = elements.stream()
.map(typeElement -> elementFactory.newSourceClassElement(typeElement, elementAnnotationMetadataFactory))
.toList();
}
typeElement is an element in collection named elements. At line 243, it checks elements is not empty, but it doesn't check each element inside not null.
In fact a null element should not have been added to this collection.
Can someone take a look and fix it?
Discussed in https://github.com/micronaut-projects/micronaut-security/discussions/1604