This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 7c13a878cbb4 CAMEL-26220: camel-ibm-watson-discovery - manage
com.ibm.cloud:sdk-core 9.24.3, which works with the Gson of Camel, so query no
longer fails with NoClassDefFoundError for $Gson$Types (#28974)
7c13a878cbb4 is described below
commit 7c13a878cbb4126dbf51bb35d024ddda8dca9aab
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Nov 2 22:42:24 2026 +0100
CAMEL-26220: camel-ibm-watson-discovery - manage com.ibm.cloud:sdk-core
9.24.3, which works with the Gson of Camel, so query no longer fails with
NoClassDefFoundError for $Gson$Types (#28974)
* CAMEL-26220: camel-ibm-watson-discovery - manage com.ibm.cloud:sdk-core
9.24.3, which works with the Gson of Camel, so query no longer fails with
NoClassDefFoundError for $Gson$Types
* CAMEL-26220: camel-ibm - declare com.ibm.cloud:sdk-core in every module
that uses it, and keep it on 9.24.x (comment on the property, Dependabot
ignores 9.25.0 and later)
Signed-off-by: Andrea Cosentino <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.github/dependabot.yml | 3 +
.../camel-ibm/camel-ibm-secrets-manager/pom.xml | 6 +
.../camel-ibm/camel-ibm-watson-discovery/pom.xml | 6 +
.../WatsonDiscoveryProducerQueryTest.java | 148 +++++++++++++++++++++
.../camel-ibm/camel-ibm-watson-language/pom.xml | 6 +
.../camel-ibm-watson-speech-to-text/pom.xml | 6 +
.../camel-ibm-watson-text-to-speech/pom.xml | 6 +
components/camel-ibm/pom.xml | 16 +++
parent/pom.xml | 2 +
9 files changed, 199 insertions(+)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 9adb2ca29315..1a9d8fb00216 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -45,6 +45,9 @@ updates:
# Jackson 3 uses the 2.x jackson-annotations
- dependency-name: "com.fasterxml.jackson.core:jackson-annotations"
update-types: ["version-update:semver-major"]
+ # sdk-core 9.25.0 and later need OkHttp 5, and the IBM SDKs of camel-ibm
are built with OkHttp 4: revisit when they move to OkHttp 5
+ - dependency-name: "com.ibm.cloud:sdk-core"
+ versions: [">= 9.25.0"]
groups:
Aliyun:
patterns:
["com.aliyun:*","com.aliyun.openservices:*","com.aliyun.mns:*"]
diff --git a/components/camel-ibm/camel-ibm-secrets-manager/pom.xml
b/components/camel-ibm/camel-ibm-secrets-manager/pom.xml
index 98b2c6ba76ca..f1d35a6ea4e7 100644
--- a/components/camel-ibm/camel-ibm-secrets-manager/pom.xml
+++ b/components/camel-ibm/camel-ibm-secrets-manager/pom.xml
@@ -52,6 +52,12 @@
<artifactId>secrets-manager</artifactId>
<version>${ibm-secrets-manager-version}</version>
</dependency>
+ <!-- the IBM SDK core at the version managed in camel-ibm-parent,
declared here so that applications
+ run the version Camel is built and tested with, instead of the
older one of the Secrets Manager SDK -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ </dependency>
<!-- kafka java client -->
<dependency>
diff --git a/components/camel-ibm/camel-ibm-watson-discovery/pom.xml
b/components/camel-ibm/camel-ibm-watson-discovery/pom.xml
index 59f76d4db70c..cbbe0b46f352 100644
--- a/components/camel-ibm/camel-ibm-watson-discovery/pom.xml
+++ b/components/camel-ibm/camel-ibm-watson-discovery/pom.xml
@@ -48,6 +48,12 @@
<artifactId>discovery</artifactId>
<version>${ibm-watson-sdk-version}</version>
</dependency>
+ <!-- the IBM SDK core at the version managed in camel-ibm-parent,
declared here so that applications
+ get it too, instead of the older one of the Watson SDK that fails
with Gson 2.13 or later -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ </dependency>
<!-- for testing -->
<dependency>
diff --git
a/components/camel-ibm/camel-ibm-watson-discovery/src/test/java/org/apache/camel/component/ibm/watson/discovery/WatsonDiscoveryProducerQueryTest.java
b/components/camel-ibm/camel-ibm-watson-discovery/src/test/java/org/apache/camel/component/ibm/watson/discovery/WatsonDiscoveryProducerQueryTest.java
new file mode 100644
index 000000000000..af632ed8af6c
--- /dev/null
+++
b/components/camel-ibm/camel-ibm-watson-discovery/src/test/java/org/apache/camel/component/ibm/watson/discovery/WatsonDiscoveryProducerQueryTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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 org.apache.camel.component.ibm.watson.discovery;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.ibm.cloud.sdk.core.security.IamAuthenticator;
+import com.ibm.watson.discovery.v2.model.QueryResponse;
+import com.ibm.watson.discovery.v2.model.QueryResult;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * The query operation parses the response of Watson Discovery, with a JDK
HttpServer as the Discovery service and as
+ * the IAM token service. The IBM SDK core must work with the Gson that Camel
uses: sdk-core 9.20.0 of the Watson SDK
+ * uses the Gson internal class $Gson$Types, which Gson 2.13.0 renamed to
GsonTypes, so every query failed with a
+ * NoClassDefFoundError while parsing the response.
+ */
+class WatsonDiscoveryProducerQueryTest extends CamelTestSupport {
+
+ private static final String PROJECT_ID = "my-project";
+
+ private HttpServer server;
+ private volatile String queryResponse;
+ private volatile String queryRequestUri;
+ private volatile String queryRequestBody;
+ private volatile String queryAuthorization;
+
+ @Override
+ protected void setupResources() throws Exception {
+ server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
+ // the IAM token service, which the IamAuthenticator of the endpoint
asks for a token for the API key
+ server.createContext("/identity/token", exchange -> {
+ exchange.getRequestBody().readAllBytes();
+ respond(exchange,
"{\"access_token\":\"test-access-token\",\"refresh_token\":\"test-refresh-token\","
+ +
"\"token_type\":\"Bearer\",\"expires_in\":3600,\"expiration\":"
+ + (Instant.now().getEpochSecond() + 3600) + "}");
+ });
+ // the query of the Discovery v2 API
+ server.createContext("/v2/projects/" + PROJECT_ID + "/query", exchange
-> {
+ queryRequestUri = exchange.getRequestURI().toString();
+ queryRequestBody = new
String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
+ queryAuthorization =
exchange.getRequestHeaders().getFirst("Authorization");
+ respond(exchange, queryResponse);
+ });
+ server.start();
+ }
+
+ @Override
+ protected void cleanupResources() throws Exception {
+ if (server != null) {
+ server.stop(0);
+ }
+ }
+
+ @BeforeEach
+ void useStubTokenService() {
+ // the endpoint authenticates with an IAM API key: take the token from
the stub instead of IBM Cloud
+ WatsonDiscoveryEndpoint endpoint = context.getEndpoint(discoveryUri(),
WatsonDiscoveryEndpoint.class);
+ ((IamAuthenticator)
endpoint.getDiscoveryClient().getAuthenticator()).setURL(serverUrl());
+ }
+
+ @Test
+ void queryParsesResponseWithoutResults() {
+ queryResponse = "{\"matching_results\":0}";
+
+ QueryResponse response = template.requestBody("direct:query", "What is
Apache Camel?", QueryResponse.class);
+
+ assertEquals(0L, response.getMatchingResults());
+ assertNull(response.getResults());
+ }
+
+ @Test
+ void queryParsesResultsWithDynamicProperties() {
+ queryResponse =
"{\"matching_results\":1,\"results\":[{\"document_id\":\"doc-1\",\"title\":\"Apache
Camel\","
+ +
"\"result_metadata\":{\"collection_id\":\"col-1\",\"confidence\":0.9}}]}";
+
+ QueryResponse response = template.requestBody("direct:query", "What is
Apache Camel?", QueryResponse.class);
+
+ assertEquals(1L, response.getMatchingResults());
+ assertEquals(1, response.getResults().size());
+ QueryResult result = response.getResults().get(0);
+ assertEquals("doc-1", result.getDocumentId());
+ // a property the model does not declare is kept as a dynamic property
of the result
+ assertEquals("Apache Camel", result.get("title"));
+ assertEquals("col-1", result.getResultMetadata().getCollectionId());
+
+ assertEquals("/v2/projects/" + PROJECT_ID +
"/query?version=2023-03-31", queryRequestUri);
+ JsonObject request =
JsonParser.parseString(queryRequestBody).getAsJsonObject();
+ assertEquals("What is Apache Camel?",
request.get("natural_language_query").getAsString());
+ assertEquals("Bearer test-access-token", queryAuthorization);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:query").to(discoveryUri());
+ }
+ };
+ }
+
+ private String serverUrl() {
+ return "http://localhost:" + server.getAddress().getPort();
+ }
+
+ private String discoveryUri() {
+ return "ibm-watson-discovery:test?apiKey=test-api-key&projectId=" +
PROJECT_ID + "&operation=query&serviceUrl="
+ + serverUrl();
+ }
+
+ private static void respond(HttpExchange exchange, String json) throws
IOException {
+ byte[] body = json.getBytes(StandardCharsets.UTF_8);
+ exchange.getResponseHeaders().set("Content-Type", "application/json");
+ exchange.sendResponseHeaders(200, body.length);
+ try (OutputStream out = exchange.getResponseBody()) {
+ out.write(body);
+ }
+ }
+}
diff --git a/components/camel-ibm/camel-ibm-watson-language/pom.xml
b/components/camel-ibm/camel-ibm-watson-language/pom.xml
index df433c1076af..23a4fb5e6d8d 100644
--- a/components/camel-ibm/camel-ibm-watson-language/pom.xml
+++ b/components/camel-ibm/camel-ibm-watson-language/pom.xml
@@ -48,6 +48,12 @@
<artifactId>natural-language-understanding</artifactId>
<version>${ibm-watson-sdk-version}</version>
</dependency>
+ <!-- the IBM SDK core at the version managed in camel-ibm-parent,
declared here so that applications
+ run the version Camel is built and tested with, instead of the
older one of the Watson SDK -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ </dependency>
<!-- for testing -->
<dependency>
diff --git a/components/camel-ibm/camel-ibm-watson-speech-to-text/pom.xml
b/components/camel-ibm/camel-ibm-watson-speech-to-text/pom.xml
index 4eed2c32e27c..b8a6565f749e 100644
--- a/components/camel-ibm/camel-ibm-watson-speech-to-text/pom.xml
+++ b/components/camel-ibm/camel-ibm-watson-speech-to-text/pom.xml
@@ -48,6 +48,12 @@
<artifactId>speech-to-text</artifactId>
<version>${ibm-watson-sdk-version}</version>
</dependency>
+ <!-- the IBM SDK core at the version managed in camel-ibm-parent,
declared here so that applications
+ run the version Camel is built and tested with, instead of the
older one of the Watson SDK -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ </dependency>
<!-- for testing -->
<dependency>
diff --git a/components/camel-ibm/camel-ibm-watson-text-to-speech/pom.xml
b/components/camel-ibm/camel-ibm-watson-text-to-speech/pom.xml
index 47e495a47f4d..66c343f3774c 100644
--- a/components/camel-ibm/camel-ibm-watson-text-to-speech/pom.xml
+++ b/components/camel-ibm/camel-ibm-watson-text-to-speech/pom.xml
@@ -48,6 +48,12 @@
<artifactId>text-to-speech</artifactId>
<version>${ibm-watson-sdk-version}</version>
</dependency>
+ <!-- the IBM SDK core at the version managed in camel-ibm-parent,
declared here so that applications
+ run the version Camel is built and tested with, instead of the
older one of the Watson SDK -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ </dependency>
<!-- for testing -->
<dependency>
diff --git a/components/camel-ibm/pom.xml b/components/camel-ibm/pom.xml
index 7bad50a6f4fb..d51abf4fa13b 100644
--- a/components/camel-ibm/pom.xml
+++ b/components/camel-ibm/pom.xml
@@ -43,4 +43,20 @@
<module>camel-ibm-watsonx-data</module>
</modules>
+ <dependencyManagement>
+ <dependencies>
+ <!-- The IBM SDKs bring an older com.ibm.cloud:sdk-core (9.20.0
for Watson 16.2.0, 9.18.4 for
+ watsonx.data 0.9.0) that uses the Gson internal class
$Gson$Types, which Gson 2.13.0 renamed
+ to GsonTypes: with the Gson of camel-parent, parsing a
response whose model has dynamic
+ properties fails with NoClassDefFoundError. sdk-core 9.23.1
and later use GsonTypes; 9.24.x
+ is the last line on OkHttp 4, which the IBM SDKs are built
with (9.25.0 moved to OkHttp 5).
+ Each module that uses sdk-core also declares it, so that
applications get this version too. -->
+ <dependency>
+ <groupId>com.ibm.cloud</groupId>
+ <artifactId>sdk-core</artifactId>
+ <version>${ibm-sdk-core-version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
</project>
diff --git a/parent/pom.xml b/parent/pom.xml
index 238c4cc4bb25..16951363a151 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -251,6 +251,8 @@
<huaweicloud-obs-version>3.26.9</huaweicloud-obs-version>
<huaweicloud-sdk-version>3.1.222</huaweicloud-sdk-version>
<ibm-cos-sdk-version>2.15.1</ibm-cos-sdk-version>
+ <!-- stay on sdk-core 9.24.x: 9.25.0 and later need OkHttp 5, and the
IBM SDKs of camel-ibm are built with OkHttp 4 (see
components/camel-ibm/pom.xml) -->
+ <ibm-sdk-core-version>9.24.3</ibm-sdk-core-version>
<ibm-secrets-manager-version>2.0.28</ibm-secrets-manager-version>
<ibm-watson-sdk-version>16.2.0</ibm-watson-sdk-version>
<ibm-watsonx-ai-sdk-version>0.40.0</ibm-watsonx-ai-sdk-version>