This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new af9afc3d3a Work around issues for avro-jackson compatibility with Avro
1.12.x
af9afc3d3a is described below
commit af9afc3d3a8bc636f443087560cfe21dec414bbd
Author: James Netherton <[email protected]>
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"));
+ }
}