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

jamesnetherton pushed a commit to branch 3.15.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 3ebbabcf94e252acd911fe78c780160492576d7b
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Wed Oct 30 15:59:09 2024 +0000

    Work around issues for avro-jackson compatibility with Avro 1.12.x
    
    Fixes #6721
---
 .../avro/deployment/JacksonAvroProcessor.java      | 50 ++++++++++++++++++++++
 .../jackson/avro/it/JacksonAvroResource.java       | 36 ++++++++++++++++
 .../component/jackson/avro/it/JacksonAvroTest.java | 13 ++++++
 3 files changed, 99 insertions(+)

diff --git 
a/extensions/jackson-avro/deployment/src/main/java/org/apache/camel/quarkus/component/jackson/avro/deployment/JacksonAvroProcessor.java
 
b/extensions/jackson-avro/deployment/src/main/java/org/apache/camel/quarkus/component/jackson/avro/deployment/JacksonAvroProcessor.java
index 9d9923e786..86e71872ab 100644
--- 
a/extensions/jackson-avro/deployment/src/main/java/org/apache/camel/quarkus/component/jackson/avro/deployment/JacksonAvroProcessor.java
+++ 
b/extensions/jackson-avro/deployment/src/main/java/org/apache/camel/quarkus/component/jackson/avro/deployment/JacksonAvroProcessor.java
@@ -16,10 +16,18 @@
  */
 package org.apache.camel.quarkus.component.jackson.avro.deployment;
 
+import java.util.function.BooleanSupplier;
+
 import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
 import 
io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
+import io.quarkus.gizmo.Gizmo;
+import org.apache.avro.Schema.Parser;
 import org.apache.avro.file.DataFileWriter;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 
 class JacksonAvroProcessor {
     private static final String FEATURE = "camel-jackson-avro";
@@ -33,4 +41,46 @@ class JacksonAvroProcessor {
     RuntimeInitializedClassBuildItem runtimeInitializedClass() {
         return new 
RuntimeInitializedClassBuildItem(DataFileWriter.class.getName());
     }
+
+    @BuildStep(onlyIfNot = { AvroParserSetValidateMethodPresent.class })
+    BytecodeTransformerBuildItem patchAvroJacksonCompatibility() {
+        // Hack to maintain avro-jackson compatibility with Avro 1.12.x
+        // Adds a noop version of Parser.setValidate that got removed in Avro 
1.12.x.
+        // public Parser setValidate(boolean validate) {
+        //     return this;
+        // }
+        return new BytecodeTransformerBuildItem.Builder()
+                .setClassToTransform(Parser.class.getName())
+                .setCacheable(true)
+                .setVisitorFunction((className, classVisitor) -> {
+                    return new ClassVisitor(Gizmo.ASM_API_VERSION, 
classVisitor) {
+                        @Override
+                        public void visitEnd() {
+                            MethodVisitor mv = 
cv.visitMethod(Opcodes.ACC_PUBLIC, "setValidate",
+                                    "(Z)Lorg/apache/avro/Schema$Parser;", 
null, null);
+                            if (mv != null) {
+                                mv.visitCode();
+                                mv.visitVarInsn(Opcodes.ALOAD, 0);
+                                mv.visitInsn(Opcodes.ARETURN);
+                                mv.visitMaxs(1, 2);
+                                mv.visitEnd();
+                            }
+                            super.visitEnd();
+                        }
+                    };
+                })
+                .build();
+    }
+
+    static class AvroParserSetValidateMethodPresent implements BooleanSupplier 
{
+        @Override
+        public boolean getAsBoolean() {
+            try {
+                Parser.class.getDeclaredMethod("setValidate", boolean.class);
+                return true;
+            } catch (NoSuchMethodException e) {
+                return false;
+            }
+        }
+    }
 }
diff --git 
a/integration-tests/jackson-avro/src/main/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroResource.java
 
b/integration-tests/jackson-avro/src/main/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroResource.java
index 85da1b0e43..3272edc07a 100644
--- 
a/integration-tests/jackson-avro/src/main/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroResource.java
+++ 
b/integration-tests/jackson-avro/src/main/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroResource.java
@@ -18,6 +18,9 @@ package org.apache.camel.quarkus.component.jackson.avro.it;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringJoiner;
@@ -30,14 +33,19 @@ import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import jakarta.inject.Named;
 import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 import org.apache.avro.Schema;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.jackson.SchemaResolver;
 import org.apache.camel.component.jackson.avro.JacksonAvroDataFormat;
+import org.apache.commons.io.IOUtils;
 
 @Path("/jackson-avro")
 @ApplicationScoped
@@ -93,6 +101,34 @@ public class JacksonAvroResource {
         return builder.build();
     }
 
+    @Path("/custom/mapper")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String customMapper(@QueryParam("schemaFrom") String schemaFrom) 
throws IOException {
+        AvroMapper avroMapper = new AvroMapper();
+        AvroSchema avroSchema;
+
+        if (schemaFrom.equals("classpath")) {
+            avroSchema = 
avroMapper.schemaFrom(JacksonAvroResource.class.getResourceAsStream("/pojo.avsc"));
+        } else if (schemaFrom.equals("string")) {
+            try (InputStream stream = 
JacksonAvroResource.class.getResourceAsStream("/pojo.avsc")) {
+                avroSchema = avroMapper.schemaFrom(IOUtils.toString(stream, 
StandardCharsets.UTF_8));
+            }
+        } else if (schemaFrom.equals("file")) {
+            java.nio.file.Path schemaFile = Paths.get("target/schema.avsc");
+            try (InputStream stream = 
JacksonAvroResource.class.getResourceAsStream("/pojo.avsc")) {
+                Files.write(schemaFile, stream.readAllBytes());
+                avroSchema = avroMapper.schemaFrom(schemaFile.toFile());
+            } finally {
+                Files.deleteIfExists(schemaFile);
+            }
+        } else {
+            throw new IllegalArgumentException("Unknown schema from option: " 
+ schemaFrom);
+        }
+
+        return avroSchema.getAvroSchema().getName();
+    }
+
     @Named
     public SchemaResolver avroSchemaResolver() throws IOException {
         return createSchemaResolver("/pojo.avsc");
diff --git 
a/integration-tests/jackson-avro/src/test/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroTest.java
 
b/integration-tests/jackson-avro/src/test/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroTest.java
index c00c2e6072..0b11cdc83a 100644
--- 
a/integration-tests/jackson-avro/src/test/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroTest.java
+++ 
b/integration-tests/jackson-avro/src/test/java/org/apache/camel/quarkus/component/jackson/avro/it/JacksonAvroTest.java
@@ -19,6 +19,8 @@ package org.apache.camel.quarkus.component.jackson.avro.it;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import static 
org.apache.camel.quarkus.component.jackson.avro.it.StringAppendingDeserializer.STRING_TO_APPEND;
 import static org.hamcrest.Matchers.equalTo;
@@ -87,4 +89,15 @@ class JacksonAvroTest {
                 .statusCode(200)
                 .body(equalTo(message));
     }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "classpath", "file", "string" })
+    public void customAvroMapper(String schemaFrom) {
+        RestAssured.given()
+                .queryParam("schemaFrom", schemaFrom)
+                .get("/jackson-avro/custom/mapper")
+                .then()
+                .statusCode(200)
+                .body(equalTo("Pojo"));
+    }
 }

Reply via email to