This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 7da8450629 fix: Fix Java type for annotated array parameters (#3797)
7da8450629 is described below

commit 7da84506296b6cd836475e27ce85404a28a3d5ee
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Thu Jul 3 16:55:32 2025 +0200

    fix: Fix Java type for annotated array parameters (#3797)
    
    This update fixes the GraalVM reachability metadata generation for methods 
with annotated array parameters, such as `@Nullable String[]`.
    
    Previously, the code computed the fully qualified class name for the 
parameter using the **raw** type, which retained the annotations (e.g., 
`@org.jspecify.annotations.Nullable java.lang.String`). This resulted in 
incorrect metadata that was ignored by GraalVM.
    
    The issue is resolved by transforming the `DeclaredType` into a 
`TypeElement`, effectively removing any annotations, and then calling 
`getQualifiedName()` to correctly generate the fully qualified class name 
without annotations.
---
 .../plugins/processor/GraalVmProcessorTest.java    | 24 +++++++++--
 .../GraalVmProcessorTest/java/FakeConverter.java   | 46 ++++++++++++++++++++++
 .../config/plugins/processor/GraalVmProcessor.java |  4 +-
 .../.2.x.x/3796_annotated-array-parameters.xml     | 12 ++++++
 4 files changed, 81 insertions(+), 5 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
index 9bdbcad8dd..957bb3228c 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessorTest.java
@@ -103,6 +103,18 @@ class GraalVmProcessorTest {
     private static final Object FAKE_CONSTRAINT_VALIDATOR = 
onlyNoArgsConstructor(FAKE_CONSTRAINT_VALIDATOR_NAME);
     private static final String FAKE_PLUGIN_VISITOR_NAME = 
"example.FakeAnnotations$FakePluginVisitor";
     private static final Object FAKE_PLUGIN_VISITOR = 
onlyNoArgsConstructor(FAKE_PLUGIN_VISITOR_NAME);
+    private static final String FAKE_CONVERTER_NAME = "example.FakeConverter";
+    private static final Object FAKE_CONVERTER = asMap(
+            "name",
+            FAKE_CONVERTER_NAME,
+            "methods",
+            singletonList(asMap(
+                    "name",
+                    "newInstance",
+                    "parameterTypes",
+                    
asList("org.apache.logging.log4j.core.config.Configuration", 
"java.lang.String[]"))),
+            "fields",
+            emptyList());
 
     private static final String GROUP_ID = "groupId";
     private static final String ARTIFACT_ID = "artifactId";
@@ -155,7 +167,8 @@ class GraalVmProcessorTest {
                 Arguments.of(FAKE_PLUGIN_BUILDER_NAME, FAKE_PLUGIN_BUILDER),
                 Arguments.of(FAKE_PLUGIN_NESTED_NAME, FAKE_PLUGIN_NESTED),
                 Arguments.of(FAKE_CONSTRAINT_VALIDATOR_NAME, 
FAKE_CONSTRAINT_VALIDATOR),
-                Arguments.of(FAKE_PLUGIN_VISITOR_NAME, FAKE_PLUGIN_VISITOR));
+                Arguments.of(FAKE_PLUGIN_VISITOR_NAME, FAKE_PLUGIN_VISITOR),
+                Arguments.of(FAKE_CONVERTER_NAME, FAKE_CONVERTER));
     }
 
     @ParameterizedTest
@@ -168,7 +181,9 @@ class GraalVmProcessorTest {
         assertThatJson(reachabilityMetadata)
                 .inPath(String.format("$[?(@.name == '%s')]", className))
                 .isArray()
-                .contains(json(expectedJson));
+                .hasSize(1)
+                .first()
+                .isEqualTo(json(expectedJson));
     }
 
     static Stream<Arguments> reachabilityMetadataPath() {
@@ -214,7 +229,7 @@ class GraalVmProcessorTest {
         }
         // The generated folder name should be deterministic and based solely 
on the descriptor content.
         // If the descriptor changes, this test and the expected folder name 
must be updated accordingly.
-        
assertThat(reachabilityMetadataFolders).hasSize(1).containsExactly(path.resolve("62162090"));
+        
assertThat(reachabilityMetadataFolders).hasSize(1).containsExactly(path.resolve("72c240aa"));
         
assertThat(reachabilityMetadataFolders.get(0).resolve("reflect-config.json"))
                 .as("Reachability metadata file")
                 .exists();
@@ -250,7 +265,6 @@ class GraalVmProcessorTest {
         }
 
         // Compile the sources
-        final Path descriptorFilePath = outputDir.resolve("plugins.xml");
         final DiagnosticCollector<JavaFileObject> diagnosticCollector = new 
DiagnosticCollector<>();
         final JavaCompiler.CompilationTask task =
                 compiler.getTask(null, fileManager, diagnosticCollector, 
options, null, sources);
@@ -260,6 +274,8 @@ class GraalVmProcessorTest {
         return diagnosticCollector.getDiagnostics().stream()
                 .filter(d -> d.getKind() != Diagnostic.Kind.NOTE)
                 .map(d -> d.getMessage(Locale.ROOT))
+                // This message appears when the test runs on JDK 8
+                .filter(m -> !"unknown enum constant 
java.lang.annotation.ElementType.MODULE".equals(m))
                 .collect(Collectors.toList());
     }
 }
diff --git 
a/log4j-core-test/src/test/resources/GraalVmProcessorTest/java/FakeConverter.java
 
b/log4j-core-test/src/test/resources/GraalVmProcessorTest/java/FakeConverter.java
new file mode 100644
index 0000000000..0b15cb4ecc
--- /dev/null
+++ 
b/log4j-core-test/src/test/resources/GraalVmProcessorTest/java/FakeConverter.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.pattern.ConverterKeys;
+import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
+import org.apache.logging.log4j.core.pattern.PatternConverter;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+@Plugin(name = "FakePatternConverter", category = PatternConverter.CATEGORY)
+@ConverterKeys({"f", "fake"})
+public final class FakeConverter extends LogEventPatternConverter {
+
+    private FakeConverter(@Nullable final Configuration config, @Nullable 
final String[] options) {
+        super("Fake", "fake");
+    }
+
+    public static FakeConverter newInstance(
+            @Nullable final Configuration config, @Nullable final String[] 
options) {
+        return new FakeConverter(config, options);
+    }
+
+    @Override
+    public void format(LogEvent event, StringBuilder toAppendTo) {
+        toAppendTo.append("FakeConverter: 
").append(event.getMessage().getFormattedMessage());
+    }
+}
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
index e6178f2a17..a5ba7ba61c 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/processor/GraalVmProcessor.java
@@ -300,7 +300,9 @@ public class GraalVmProcessor extends AbstractProcessor {
 
                     @Override
                     public @Nullable String visitDeclared(final DeclaredType 
t, final Void unused) {
-                        return 
processingEnv.getTypeUtils().erasure(t).toString();
+                        return safeCast(t.asElement(), TypeElement.class)
+                                .getQualifiedName()
+                                .toString();
                     }
                 },
                 null);
diff --git a/src/changelog/.2.x.x/3796_annotated-array-parameters.xml 
b/src/changelog/.2.x.x/3796_annotated-array-parameters.xml
new file mode 100644
index 0000000000..5be57fe641
--- /dev/null
+++ b/src/changelog/.2.x.x/3796_annotated-array-parameters.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+           https://logging.apache.org/xml/ns
+           https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="fixed">
+    <issue id="3796" 
link="https://github.com/apache/logging-log4j2/issues/3796"/>
+    <description format="asciidoc">
+        Fix GraalVM reachability metadata generation for methods with 
annotated array type parameters, such as `@Nullable String[]`.
+    </description>
+</entry>

Reply via email to