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

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


The following commit(s) were added to refs/heads/camel-4.22.x by this push:
     new 50352373fe50 camel-ibm MED fixes backport to camel-4.22.x 
(CAMEL-24488, 24490, 24491, 24493) (#25782)
50352373fe50 is described below

commit 50352373fe50a7b28952d4c18b081e0173c2386a
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Aug 27 11:19:36 2026 +0200

    camel-ibm MED fixes backport to camel-4.22.x (CAMEL-24488, 24490, 24491, 
24493) (#25782)
    
    * CAMEL-24488: camel-ibm-watson-speech-to-text - close the audio 
FileInputStream opened by the producer (#25737)
    
    WatsonSpeechToTextProducer.recognize() opened a FileInputStream for the 
audio
    input (from the CamelIbmWatsonSttAudioFile header or a File body) but never
    closed it, leaking a file descriptor on every File-based invocation and on 
any
    exception thrown during recognition. Track an ownStream flag (set only for 
the
    two producer-opened FileInputStream cases) and close the stream via
    IOHelper.close in a finally block around the recognition. A stream supplied 
as
    the exchange body is owned by the caller and is left untouched.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
    
    * CAMEL-24490: camel-ibm-watsonx-ai - apply the configured timeout to the 
watsonx.ai service clients (#25739)
    
    WatsonxAiServiceFactory built every watsonx.ai service (chat, text 
generation,
    embedding, rerank, tokenization, detection, text extraction/classification,
    time series, foundation model, deployment, tool) without applying the 
timeout
    @UriParam, so the documented "Request timeout in milliseconds" option was
    silently ignored and every request used the SDK default. Apply the 
configured
    timeout to each builder via
    applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t))).
    The SDK then governs how the timeout applies to both unary and streaming
    requests, so the streaming CompletableFuture is no longer left unbounded 
when a
    timeout is configured.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
    
    * CAMEL-24493: camel-ibm-cos - honor the multiPartUpload, partSize, 
storageClass and deleteAfterWrite producer options (#25750)
    
    IBMCOSProducer.putObject() built a plain PutObjectRequest and ignored the 
four
    producer options declared on IBMCOSConfiguration and advertised in the docs.
    Apply them, mirroring camel-aws2-s3: set storageClass on the request, 
upload via
    the SDK TransferManager (minimum part size / multipart threshold = 
partSize) when
    multiPartUpload is enabled, and delete the local File payload after a 
successful
    upload when deleteAfterWrite is set.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
    
    * CAMEL-24491: camel-ibm-cos - make consumer in-progress deduplication 
effective (#25740)
    
    * CAMEL-24491: camel-ibm-cos - make consumer in-progress deduplication 
effective
    
    The IBM COS consumer's in-progress deduplication never worked: 
createExchanges()
    only checked getInProgressRepository().contains(key) without ever adding the
    key, the MemoryIdempotentRepository was started only after doStart()'s early
    returns (so never in the normal consuming case), and 
processCommit/processRollback
    never removed the key. As a result overlapping polls could re-deliver an 
object
    still being processed when deleteAfterRead/moveAfterRead were off.
    
    Mirror the camel-aws2-s3 consumer this module was copied from: use
    getInProgressRepository().add(key) as the atomic guard (skip when it returns
    false), remove the key in processCommit (finally) and processRollback via a
    null-safe helper, and start the in-progress repository up front in doStart()
    before any early return.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * CAMEL-24491: release the in-progress key when the object fetch or 
exchange creation fails
    
    Addresses review feedback: if getObject/createExchange throws after add(key)
    has claimed the in-progress key, no Synchronization is attached to remove 
it, so
    the object would be left permanently unconsumable. Release the key (and 
skip the
    object for this poll) so a transient failure does not silently block the 
object.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 .../camel/component/ibm/cos/IBMCOSConsumer.java    | 27 +++++++++--
 .../camel/component/ibm/cos/IBMCOSEndpoint.java    |  5 +-
 .../camel/component/ibm/cos/IBMCOSProducer.java    | 51 ++++++++++++++++++--
 .../ibm/watson/stt/WatsonSpeechToTextProducer.java | 56 +++++++++++++---------
 .../ai/service/WatsonxAiServiceFactory.java        | 13 +++++
 5 files changed, 119 insertions(+), 33 deletions(-)

diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
index 233723ac43f7..66de7917f054 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
@@ -160,15 +160,23 @@ public class IBMCOSConsumer extends 
ScheduledBatchPollingConsumer {
             }
 
             if (getEndpoint().getInProgressRepository() != null
-                    && 
getEndpoint().getInProgressRepository().contains(s3ObjectSummary.getKey())) {
+                    && 
!getEndpoint().getInProgressRepository().add(s3ObjectSummary.getKey())) {
                 LOG.trace("Object {} is already in progress", 
s3ObjectSummary.getKey());
                 continue;
             }
 
-            S3Object s3Object = getCosClient().getObject(
-                    new GetObjectRequest(s3ObjectSummary.getBucketName(), 
s3ObjectSummary.getKey()));
-            Exchange exchange = createExchange(s3Object, 
s3ObjectSummary.getKey());
-            exchanges.add(exchange);
+            try {
+                S3Object s3Object = getCosClient().getObject(
+                        new GetObjectRequest(s3ObjectSummary.getBucketName(), 
s3ObjectSummary.getKey()));
+                Exchange exchange = createExchange(s3Object, 
s3ObjectSummary.getKey());
+                exchanges.add(exchange);
+            } catch (Exception e) {
+                // Fetching the object or creating the exchange failed after 
we claimed the in-progress key;
+                // release it so the object is not left permanently 
unconsumable, and skip it for this poll.
+                LOG.warn("Error fetching object {} from bucket {}: {}. 
Skipping it for this poll.",
+                        s3ObjectSummary.getKey(), 
s3ObjectSummary.getBucketName(), e.getMessage());
+                removeInProgress(s3ObjectSummary.getKey());
+            }
         }
 
         return exchanges;
@@ -246,11 +254,20 @@ public class IBMCOSConsumer extends 
ScheduledBatchPollingConsumer {
             }
         } catch (Exception e) {
             LOG.warn("Error during post processing of object {} from bucket 
{}: {}", key, bucketName, e.getMessage());
+        } finally {
+            removeInProgress(key);
         }
     }
 
     protected void processRollback(String key) {
         LOG.trace("Processing failed for object with key {}", key);
+        removeInProgress(key);
+    }
+
+    private void removeInProgress(String key) {
+        if (getEndpoint().getInProgressRepository() != null) {
+            getEndpoint().getInProgressRepository().remove(key);
+        }
     }
 
     private void copyObject(String bucketName, String key) {
diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
index 63d9d5b5478b..dcbafcfd3dc9 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
@@ -115,6 +115,9 @@ public class IBMCOSEndpoint extends ScheduledPollEndpoint 
implements EndpointSer
     protected void doStart() throws Exception {
         super.doStart();
 
+        // Start the in-progress repository up front so consumer deduplication 
works even when doStart returns early
+        ServiceHelper.startService(inProgressRepository);
+
         cosClient = configuration.getCosClient() != null
                 ? configuration.getCosClient() : createCosClient();
 
@@ -146,8 +149,6 @@ public class IBMCOSEndpoint extends ScheduledPollEndpoint 
implements EndpointSer
             cosClient.createBucket(bucketName);
             LOG.trace("Bucket created");
         }
-
-        ServiceHelper.startService(inProgressRepository);
     }
 
     @Override
diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
index e8bed18528fa..c4e105af2e00 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.ibm.cos;
 
+import java.io.File;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,10 +34,14 @@ import 
com.ibm.cloud.objectstorage.services.s3.model.ObjectMetadata;
 import com.ibm.cloud.objectstorage.services.s3.model.PutObjectRequest;
 import com.ibm.cloud.objectstorage.services.s3.model.PutObjectResult;
 import com.ibm.cloud.objectstorage.services.s3.model.S3Object;
+import com.ibm.cloud.objectstorage.services.s3.transfer.TransferManager;
+import com.ibm.cloud.objectstorage.services.s3.transfer.TransferManagerBuilder;
+import com.ibm.cloud.objectstorage.services.s3.transfer.model.UploadResult;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.WrappedFile;
 import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -154,12 +159,52 @@ public class IBMCOSProducer extends DefaultProducer {
 
         PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, 
key, inputStream, metadata);
 
+        String storageClass = getConfiguration().getStorageClass();
+        if (ObjectHelper.isNotEmpty(storageClass)) {
+            putObjectRequest.withStorageClass(storageClass);
+        }
+
         LOG.trace("Putting object [{}] into bucket [{}]...", key, bucketName);
-        PutObjectResult putObjectResult = 
cosClient.putObject(putObjectRequest);
+
+        String eTag;
+        String versionId;
+        if (getConfiguration().isMultiPartUpload()) {
+            // Upload via the TransferManager so large payloads are sent as a 
multipart upload with the configured part size
+            TransferManager transferManager = TransferManagerBuilder.standard()
+                    .withS3Client(cosClient)
+                    
.withMinimumUploadPartSize(getConfiguration().getPartSize())
+                    
.withMultipartUploadThreshold(getConfiguration().getPartSize())
+                    .build();
+            try {
+                UploadResult uploadResult = 
transferManager.upload(putObjectRequest).waitForUploadResult();
+                eTag = uploadResult.getETag();
+                versionId = uploadResult.getVersionId();
+            } finally {
+                // shut down the TransferManager's own thread pool but keep 
the shared COS client open
+                transferManager.shutdownNow(false);
+            }
+        } else {
+            PutObjectResult putObjectResult = 
cosClient.putObject(putObjectRequest);
+            eTag = putObjectResult.getETag();
+            versionId = putObjectResult.getVersionId();
+        }
 
         Message message = getMessageForResponse(exchange);
-        message.setHeader(IBMCOSConstants.E_TAG, putObjectResult.getETag());
-        message.setHeader(IBMCOSConstants.VERSION_ID, 
putObjectResult.getVersionId());
+        message.setHeader(IBMCOSConstants.E_TAG, eTag);
+        message.setHeader(IBMCOSConstants.VERSION_ID, versionId);
+
+        if (getConfiguration().isDeleteAfterWrite()) {
+            File filePayload = null;
+            if (body instanceof File file) {
+                filePayload = file;
+            } else if (body instanceof WrappedFile<?> wrapped && 
wrapped.getFile() instanceof File file) {
+                filePayload = file;
+            }
+            if (filePayload != null) {
+                LOG.trace("Deleting file payload [{}] after write", 
filePayload);
+                FileUtil.deleteFile(filePayload);
+            }
+        }
     }
 
     private void getObject(AmazonS3 cosClient, Exchange exchange) {
diff --git 
a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/java/org/apache/camel/component/ibm/watson/stt/WatsonSpeechToTextProducer.java
 
b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/java/org/apache/camel/component/ibm/watson/stt/WatsonSpeechToTextProducer.java
index c732fecfbe7f..eaed1831268d 100644
--- 
a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/java/org/apache/camel/component/ibm/watson/stt/WatsonSpeechToTextProducer.java
+++ 
b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/java/org/apache/camel/component/ibm/watson/stt/WatsonSpeechToTextProducer.java
@@ -35,6 +35,7 @@ import 
com.ibm.watson.speech_to_text.v1.model.SpeechRecognitionResults;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.IOHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -100,15 +101,18 @@ public class WatsonSpeechToTextProducer extends 
DefaultProducer {
         // Get audio input from header or body
         File audioFile = 
exchange.getIn().getHeader(WatsonSpeechToTextConstants.AUDIO_FILE, File.class);
         InputStream audioStream = null;
+        boolean ownStream = false;
 
         if (audioFile != null) {
             audioStream = new FileInputStream(audioFile);
+            ownStream = true;
         } else {
             audioStream = exchange.getIn().getBody(InputStream.class);
             if (audioStream == null) {
                 File bodyFile = exchange.getIn().getBody(File.class);
                 if (bodyFile != null) {
                     audioStream = new FileInputStream(bodyFile);
+                    ownStream = true;
                 }
             }
         }
@@ -130,32 +134,38 @@ public class WatsonSpeechToTextProducer extends 
DefaultProducer {
 
         LOG.trace("Recognizing audio with STT: model={}, contentType={}", 
model, contentType);
 
-        RecognizeOptions options = new RecognizeOptions.Builder()
-                .audio(audioStream)
-                .model(model)
-                .contentType(contentType)
-                .timestamps(timestamps)
-                .wordConfidence(wordConfidence)
-                .speakerLabels(speakerLabels)
-                .build();
-
-        SpeechRecognitionResults results = 
stt.recognize(options).execute().getResult();
-
-        // Extract transcript text
-        StringBuilder transcript = new StringBuilder();
-        if (results.getResults() != null && !results.getResults().isEmpty()) {
-            for (SpeechRecognitionResult result : results.getResults()) {
-                if (result.getAlternatives() != null && 
!result.getAlternatives().isEmpty()) {
-                    
transcript.append(result.getAlternatives().get(0).getTranscript());
+        try {
+            RecognizeOptions options = new RecognizeOptions.Builder()
+                    .audio(audioStream)
+                    .model(model)
+                    .contentType(contentType)
+                    .timestamps(timestamps)
+                    .wordConfidence(wordConfidence)
+                    .speakerLabels(speakerLabels)
+                    .build();
+
+            SpeechRecognitionResults results = 
stt.recognize(options).execute().getResult();
+
+            // Extract transcript text
+            StringBuilder transcript = new StringBuilder();
+            if (results.getResults() != null && 
!results.getResults().isEmpty()) {
+                for (SpeechRecognitionResult result : results.getResults()) {
+                    if (result.getAlternatives() != null && 
!result.getAlternatives().isEmpty()) {
+                        
transcript.append(result.getAlternatives().get(0).getTranscript());
+                    }
                 }
             }
-        }
 
-        Message message = getMessageForResponse(exchange);
-        message.setBody(results);
-        message.setHeader(WatsonSpeechToTextConstants.TRANSCRIPT, 
transcript.toString());
-        message.setHeader(WatsonSpeechToTextConstants.MODEL, model);
-        message.setHeader(WatsonSpeechToTextConstants.CONTENT_TYPE, 
contentType);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(results);
+            message.setHeader(WatsonSpeechToTextConstants.TRANSCRIPT, 
transcript.toString());
+            message.setHeader(WatsonSpeechToTextConstants.MODEL, model);
+            message.setHeader(WatsonSpeechToTextConstants.CONTENT_TYPE, 
contentType);
+        } finally {
+            if (ownStream) {
+                IOHelper.close(audioStream);
+            }
+        }
     }
 
     private void listModels(Exchange exchange) {
diff --git 
a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/java/org/apache/camel/component/ibm/watsonx/ai/service/WatsonxAiServiceFactory.java
 
b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/java/org/apache/camel/component/ibm/watsonx/ai/service/WatsonxAiServiceFactory.java
index 70797eed2f68..74ecfe172507 100644
--- 
a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/java/org/apache/camel/component/ibm/watsonx/ai/service/WatsonxAiServiceFactory.java
+++ 
b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/java/org/apache/camel/component/ibm/watsonx/ai/service/WatsonxAiServiceFactory.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.ibm.watsonx.ai.service;
 
+import java.time.Duration;
 import java.util.function.Consumer;
 
 import com.ibm.watsonx.ai.chat.ChatService;
@@ -51,6 +52,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -66,6 +68,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -81,6 +84,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -96,6 +100,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -111,6 +116,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -126,6 +132,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         // DetectionService doesn't have modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -150,6 +157,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         // TextExtractionService doesn't have modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -171,6 +179,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         // TextClassificationService doesn't have modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -186,6 +195,7 @@ public final class WatsonxAiServiceFactory {
         applyIfNotNull(config.getSpaceId(), builder::spaceId);
         applyIfNotNull(config.getModelId(), builder::modelId);
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -198,6 +208,7 @@ public final class WatsonxAiServiceFactory {
 
         // FoundationModelService doesn't have projectId, spaceId, modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -211,6 +222,7 @@ public final class WatsonxAiServiceFactory {
 
         // DeploymentService doesn't have projectId, spaceId, modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 
@@ -231,6 +243,7 @@ public final class WatsonxAiServiceFactory {
 
         // ToolService doesn't have projectId, spaceId, modelId
         applyIfNotNull(config.getVerifySsl(), builder::verifySsl);
+        applyIfNotNull(config.getTimeout(), t -> 
builder.timeout(Duration.ofMillis(t)));
         applyIfTrue(config.getLogRequests(), () -> builder.logRequests(true));
         applyIfTrue(config.getLogResponses(), () -> 
builder.logResponses(true));
 

Reply via email to