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>

Reply via email to