This is an automated email from the ASF dual-hosted git repository. JiriOndrusek pushed a commit to branch camel-main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit f2f94184bc8a9f067424488d207ce7a7a9107928 Author: Jiri Ondrusek <[email protected]> AuthorDate: Fri Jul 10 10:02:29 2026 +0200 Fixes #8854. Adapt weaviate extension and tests for weaviate client v6 Migrate from io.weaviate:client (v5) to io.weaviate:client6 package structure, update deployment processor reflection registration, handle v6 response types (direct objects instead of Result<?> wrapper), add gRPC transport support via quarkus-grpc-common with bytecode remapping of shaded netty/grpc references (same pattern as Milvus extension). Co-Authored-By: Claude Opus 4.6 <[email protected]> --- extensions/weaviate/deployment/pom.xml | 4 ++ .../weaviate/deployment/WeaviateProcessor.java | 49 +++++++++++++++++----- extensions/weaviate/runtime/pom.xml | 4 ++ .../component/weaviate/it/WeaviateResource.java | 40 +----------------- .../component/weaviate/it/WeaviateRoutes.java | 15 ++++++- .../component/weaviate/it/WeaviateTest.java | 39 ++++++----------- .../weaviate/it/WeaviateTestResource.java | 7 +++- 7 files changed, 80 insertions(+), 78 deletions(-) diff --git a/extensions/weaviate/deployment/pom.xml b/extensions/weaviate/deployment/pom.xml index 2c0a08d297..8430c63cdd 100644 --- a/extensions/weaviate/deployment/pom.xml +++ b/extensions/weaviate/deployment/pom.xml @@ -42,6 +42,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-netty-deployment</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-grpc-common-deployment</artifactId> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-weaviate</artifactId> diff --git a/extensions/weaviate/deployment/src/main/java/org/apache/camel/quarkus/component/weaviate/deployment/WeaviateProcessor.java b/extensions/weaviate/deployment/src/main/java/org/apache/camel/quarkus/component/weaviate/deployment/WeaviateProcessor.java index c316f8ea2f..17c8870ce2 100644 --- a/extensions/weaviate/deployment/src/main/java/org/apache/camel/quarkus/component/weaviate/deployment/WeaviateProcessor.java +++ b/extensions/weaviate/deployment/src/main/java/org/apache/camel/quarkus/component/weaviate/deployment/WeaviateProcessor.java @@ -18,12 +18,17 @@ package org.apache.camel.quarkus.component.weaviate.deployment; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem; import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.IndexDependencyBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; import org.jboss.jandex.IndexView; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.ClassRemapper; +import org.objectweb.asm.commons.Remapper; class WeaviateProcessor { @@ -40,28 +45,52 @@ class WeaviateProcessor { String[] dtos = index.getKnownClasses().stream() .map(ci -> ci.name().toString()) - .filter(n -> n.startsWith("io.weaviate.client.v1.") - && n.contains(".model")) + .filter(n -> n.startsWith("io.weaviate.client6.v1.api.")) .sorted() .toArray(String[]::new); reflectiveClass.produce(ReflectiveClassBuildItem.builder(dtos).methods().fields().build()); - - //error handler - reflectiveClass.produce( - ReflectiveClassBuildItem - .builder(new String[] { "io.weaviate.client.base.WeaviateErrorResponse", - "io.weaviate.client.base.WeaviateErrorMessage", "io.weaviate.client.base.WeaviateError" }) - .methods().fields().build()); } @BuildStep IndexDependencyBuildItem registerDependencyForIndex() { - return new IndexDependencyBuildItem("io.weaviate", "client"); + return new IndexDependencyBuildItem("io.weaviate", "client6"); } @BuildStep RuntimeInitializedClassBuildItem runtimeInitializedClasses() { return new RuntimeInitializedClassBuildItem("com.google.protobuf.JavaFeaturesProto"); } + + @BuildStep + void relocateShadedGrpcCalls( + CombinedIndexBuildItem index, + BuildProducer<BytecodeTransformerBuildItem> transformers) { + + index.getIndex().getKnownClasses().stream() + .filter(ci -> ci.name().toString().startsWith("io.weaviate.client6")) + .forEach(ci -> transformers.produce(new BytecodeTransformerBuildItem( + ci.name().toString(), + (name, cv) -> new ShadedRelocationVisitor(cv)))); + } + + private static class ShadedRelocationVisitor extends ClassRemapper { + ShadedRelocationVisitor(ClassVisitor cv) { + super(Opcodes.ASM9, cv, new Remapper(Opcodes.ASM9) { + @Override + public String map(String internalName) { + if (internalName == null) { + return null; + } + if (internalName.startsWith("io/grpc/netty/shaded/io/grpc")) { + return internalName.replace("io/grpc/netty/shaded/io/grpc", "io/grpc"); + } + if (internalName.startsWith("io/grpc/netty/shaded/io/netty")) { + return internalName.replace("io/grpc/netty/shaded/io/netty", "io/netty"); + } + return super.map(internalName); + } + }); + } + } } diff --git a/extensions/weaviate/runtime/pom.xml b/extensions/weaviate/runtime/pom.xml index 16166e0651..64d944bfdd 100644 --- a/extensions/weaviate/runtime/pom.xml +++ b/extensions/weaviate/runtime/pom.xml @@ -52,6 +52,10 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-weaviate</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-grpc-common</artifactId> + </dependency> </dependencies> <build> diff --git a/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateResource.java b/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateResource.java index 331d1daf75..3cdcea69ef 100644 --- a/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateResource.java +++ b/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateResource.java @@ -22,10 +22,7 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; -import io.weaviate.client6.v1.api.collections.Vectors; import io.weaviate.client6.v1.api.collections.WeaviateObject; -import io.weaviate.client6.v1.api.collections.aggregate.AggregateResponse; -import io.weaviate.client6.v1.api.collections.data.InsertManyResponse; import io.weaviate.client6.v1.api.collections.query.QueryResponse; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -36,8 +33,6 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; -import org.apache.camel.component.weaviate.WeaviateVectorDbAction; -import org.apache.camel.component.weaviate.WeaviateVectorDbHeaders; import org.jboss.logging.Logger; @Path("/weaviate") @@ -66,32 +61,8 @@ public class WeaviateResource { headers.remove("body"); if (body instanceof List) { - String action = String.valueOf(headers.get(WeaviateVectorDbHeaders.ACTION)); - if (WeaviateVectorDbAction.BATCH_CREATE.name().equals(action)) { - body = ((List<Map<String, Object>>) body).stream().map(m -> { - Map<String, Object> props = (Map<String, Object>) m.get("properties"); - List<Number> vector = (List<Number>) m.get("vector"); - float[] floatVector = new float[vector.size()]; - for (int i = 0; i < vector.size(); i++) { - floatVector[i] = vector.get(i).floatValue(); - } - return new WeaviateObject.Builder<Map<String, Object>>() - .properties(props) - .vectors(Vectors.of(floatVector)) - .build(); - }).collect(Collectors.toList()); - } else { - body = ((List<?>) body).stream().map(o -> o instanceof Double ? ((Double) o).floatValue() : o) - .collect(Collectors.toList()); - } - } - - Object queryVector = headers.get(WeaviateVectorDbHeaders.QUERY_VECTOR); - if (queryVector instanceof List) { - headers.put(WeaviateVectorDbHeaders.QUERY_VECTOR, - ((List<?>) queryVector).stream() - .map(o -> o instanceof Double ? ((Double) o).floatValue() : o) - .collect(Collectors.toList())); + body = ((List<?>) body).stream().map(o -> o instanceof Double ? ((Double) o).floatValue() : o) + .collect(Collectors.toList()); } Exchange response = context.createFluentProducerTemplate() @@ -124,13 +95,6 @@ public class WeaviateResource { WeaviateObject<Map<String, Object>> wo = opt.get(); map.put("result", Map.of(wo.uuid(), wo.properties())); } - } else if (result instanceof InsertManyResponse) { - InsertManyResponse imr = (InsertManyResponse) result; - map.put("uuids", imr.uuids()); - map.put("errors", imr.errors()); - } else if (result instanceof AggregateResponse) { - AggregateResponse ar = (AggregateResponse) result; - map.put("totalCount", ar.totalCount()); } else if (result instanceof QueryResponse) { QueryResponse<Map<String, Object>> qr = (QueryResponse<Map<String, Object>>) result; List<Map<String, Object>> objects = qr.objects().stream() diff --git a/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateRoutes.java b/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateRoutes.java index a32a500461..9edecdb1e7 100644 --- a/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateRoutes.java +++ b/integration-tests/weaviate/src/main/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateRoutes.java @@ -28,6 +28,12 @@ public class WeaviateRoutes extends RouteBuilder { @ConfigProperty(name = WeaviateResource.WEAVIATE_CONTAINER_ADDRESS) Optional<String> weaviateContainerAddress; + @ConfigProperty(name = WeaviateResource.WEAVIATE_CONTAINER_GRPC_HOST) + Optional<String> weaviateGrpcHost; + + @ConfigProperty(name = WeaviateResource.WEAVIATE_CONTAINER_GRPC_PORT) + Optional<String> weaviateGrpcPort; + @ConfigProperty(name = WeaviateResource.WEAVIATE_HOST_ENV) Optional<String> host; @@ -42,7 +48,14 @@ public class WeaviateRoutes extends RouteBuilder { private String getUrl() { if (weaviateContainerAddress.isPresent()) { - return "weaviate:test-collection?scheme=http&host=" + weaviateContainerAddress.get(); + String url = "weaviate:test-collection?host=" + weaviateContainerAddress.get(); + if (weaviateGrpcHost.isPresent()) { + url += "&grpcHost=" + weaviateGrpcHost.get(); + } + if (weaviateGrpcPort.isPresent()) { + url += "&grpcPort=" + weaviateGrpcPort.get(); + } + return url; } if (host.isPresent() && apiKey.isPresent()) { diff --git a/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTest.java b/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTest.java index 331b2d5d62..c88640d791 100644 --- a/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTest.java +++ b/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTest.java @@ -78,12 +78,8 @@ class WeaviateTest { if (collectionCreated) { deleteCollection(collectionName); - //verify that collection is removed query(collectionName, Arrays.asList(0.15f, 0.25f, 0.35f), Map.of("title", "", "content", ""), true) - .body("error.statusCode", Matchers.equalTo(422)) - .body("error.messages.message", - Matchers.hasItem( - "no graphql provider present, this is most likely because no schema is present. Import a schema first!")); + .body("error", Matchers.not(IsEmptyString.emptyOrNullString())); } } } @@ -106,25 +102,23 @@ class WeaviateTest { Map.of("title", "Third Article", "content", "The content of the third article.")); query(collectionName, Arrays.asList(0.15f, 0.25f, 0.35f), Map.of("title", "", "content", "")) - .body("result.data.Get." + collectionName, Matchers.hasSize(2)) - .body("result.data.Get." + collectionName + "[0]", Matchers.aMapWithSize(2)) - .body("result.data.Get." + collectionName + "[0].title", Matchers.equalTo("Second Article")) - .body("result.data.Get." + collectionName + "[1].title", Matchers.equalTo("First Article")); + .body("result", Matchers.hasSize(2)) + .body("result[0]", Matchers.aMapWithSize(2)) + .body("result[0].title", Matchers.equalTo("Second Article")) + .body("result[1].title", Matchers.equalTo("First Article")); query(collectionName, Arrays.asList(0.3f, 0.4f, 0.5f), Map.of("title", "", "content", "")) - .body("result.data.Get." + collectionName, Matchers.hasSize(2)) - .body("result.data.Get." + collectionName + "[0]", Matchers.aMapWithSize(2)) - .body("result.data.Get." + collectionName + "[0].title", Matchers.equalTo("Third Article")) - .body("result.data.Get." + collectionName + "[1].title", Matchers.equalTo("Second Article")); + .body("result", Matchers.hasSize(2)) + .body("result[0]", Matchers.aMapWithSize(2)) + .body("result[0].title", Matchers.equalTo("Third Article")) + .body("result[1].title", Matchers.equalTo("Second Article")); } finally { if (collectionCreated) { deleteCollection(collectionName); - //verify that collection is removed query(collectionName, Arrays.asList(0.15f, 0.25f, 0.35f), Map.of("title", "", "content", ""), true) - .body("error.statusCode", Matchers.equalTo(422)); - //message is already covered by operation test + .body("error", Matchers.not(IsEmptyString.emptyOrNullString())); } } } @@ -137,7 +131,6 @@ class WeaviateTest { .post("/weaviate/request") .then() .statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()) .body("result", Matchers.is(true)); } @@ -149,7 +142,6 @@ class WeaviateTest { .post("/weaviate/request") .then() .statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()) .body("result", Matchers.is(true)); } @@ -167,7 +159,6 @@ class WeaviateTest { .post("/weaviate/request") .then() .statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()) .extract().path("result"); Assertions.assertNotNull(createdId); @@ -186,8 +177,7 @@ class WeaviateTest { .body(payload) .post("/weaviate/request") .then() - .statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()); + .statusCode(200); } private void updateById(String collectionName, String id, List<Float> values, @@ -206,7 +196,7 @@ class WeaviateTest { .post("/weaviate/request") .then() .statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()); + .body("result", Matchers.is(true)); } public void deleteById(String collectionName, String id) { @@ -221,7 +211,6 @@ class WeaviateTest { .body(payload) .post("/weaviate/request") .then().statusCode(200) - .body("error", IsEmptyString.emptyOrNullString()) .body("result", Matchers.is(true)); } @@ -368,10 +357,6 @@ class WeaviateTest { .then() .statusCode(200); - if (!expectError) { - response.body("error", IsEmptyString.emptyOrNullString()); - } - return response; } } diff --git a/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTestResource.java b/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTestResource.java index bb69d45e5d..cd37189b21 100644 --- a/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTestResource.java +++ b/integration-tests/weaviate/src/test/java/org/apache/camel/quarkus/component/weaviate/it/WeaviateTestResource.java @@ -29,6 +29,8 @@ import org.testcontainers.weaviate.WeaviateContainer; public class WeaviateTestResource implements QuarkusTestResourceLifecycleManager { + private static final int GRPC_PORT = 50051; + private static final DockerImageName WEAVIATE_IMAGE = DockerImageName .parse(ConfigProvider.getConfig().getValue("weaviate.container.image", String.class)) .asCompatibleSubstituteFor("semitechnologies/weaviate"); @@ -38,7 +40,6 @@ public class WeaviateTestResource implements QuarkusTestResourceLifecycleManager @Override public Map<String, String> start() { - //detect real/mock backend Optional<String> apiKey = ConfigProvider.getConfig().getOptionalValue(WeaviateResource.WEAVIATE_API_KEY_ENV, String.class); Optional<String> hostKey = ConfigProvider.getConfig().getOptionalValue(WeaviateResource.WEAVIATE_HOST_ENV, @@ -53,7 +54,9 @@ public class WeaviateTestResource implements QuarkusTestResourceLifecycleManager container.start(); return Map.of( - WeaviateResource.WEAVIATE_CONTAINER_ADDRESS, container.getHttpHostAddress()); + WeaviateResource.WEAVIATE_CONTAINER_ADDRESS, container.getHttpHostAddress(), + WeaviateResource.WEAVIATE_CONTAINER_GRPC_HOST, container.getHost(), + WeaviateResource.WEAVIATE_CONTAINER_GRPC_PORT, String.valueOf(container.getMappedPort(GRPC_PORT))); } else if (!startMockBackend && !realApiProvided) { throw new IllegalStateException( "Set %s and %s env vars if you set CAMEL_QUARKUS_START_MOCK_BACKEND=false"
