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 2d640a1b9226 CAMEL-24816: camel-elasticsearch/camel-opensearch - minor 
robustness fixes
2d640a1b9226 is described below

commit 2d640a1b92265b62feca4e31e827c51e6730f81a
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 22 09:14:32 2026 +0200

    CAMEL-24816: camel-elasticsearch/camel-opensearch - minor robustness fixes
    
    Three small, shared robustness issues in camel-elasticsearch and 
camel-opensearch:
    
    - ScrollRequestIterator.close() built ClearScrollRequest with 
List.of(scrollId),
      which throws NullPointerException when the initial search returned no 
scroll id.
      The clear-scroll is now issued only when a scroll id is present.
    - ActionRequestConverter set the id from the CamelIndexId header 
unconditionally on
      a pre-built IndexRequest.Builder/UpdateRequest.Builder, overwriting a 
caller-supplied
      id with null when the header was absent. The id is now set only when the 
header is
      present. The elasticsearch document-only-mode check also uses 
Boolean.TRUE.equals()
      instead of reference equality.
    - The producer defaults the size/from headers from the endpoint 
configuration, but
      cleanup() removed only the index-name and wait-for-active-shards headers, 
so a
      defaulted size/from leaked into subsequent endpoints. They are now 
removed in
      cleanup() too, tracked with the same configXxx pattern.
    
    Adds converter unit tests in both components covering id preservation and 
header
    override for both index and update builders.
    
    Closes #26590
    
    Co-authored-by: Claude <[email protected]>
---
 .../camel/component/es/ElasticsearchProducer.java  | 27 ++++++-
 .../es/ElasticsearchScrollRequestIterator.java     | 13 ++--
 .../ElasticsearchActionRequestConverter.java       | 16 +++-
 .../ElasticsearchActionRequestConverterTest.java   | 86 ++++++++++++++++++++++
 .../component/opensearch/OpensearchProducer.java   | 15 +++-
 .../OpensearchScrollRequestIterator.java           | 13 ++--
 .../OpensearchActionRequestConverter.java          | 14 +++-
 .../OpensearchActionRequestConverterTest.java      | 86 ++++++++++++++++++++++
 8 files changed, 251 insertions(+), 19 deletions(-)

diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
index 5b60d9a543e8..20027487a64a 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
@@ -166,14 +166,18 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
                 configIndexName = true;
             }
 
+            boolean configSize = false;
             Integer size = 
message.getHeader(ElasticsearchConstants.PARAM_SIZE, Integer.class);
             if (size == null) {
                 message.setHeader(ElasticsearchConstants.PARAM_SIZE, 
configuration.getSize());
+                configSize = true;
             }
 
+            boolean configFrom = false;
             Integer from = 
message.getHeader(ElasticsearchConstants.PARAM_FROM, Integer.class);
             if (from == null) {
                 message.setHeader(ElasticsearchConstants.PARAM_FROM, 
configuration.getFrom());
+                configFrom = true;
             }
 
             Boolean enableDocumentOnlyMode = 
message.getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.class);
@@ -193,7 +197,8 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
                 documentClass = configuration.getDocumentClass();
             }
 
-            ActionContext ctx = new ActionContext(exchange, callback, 
transport, configIndexName, configWaitForActiveShards);
+            ActionContext ctx = new ActionContext(
+                    exchange, callback, transport, configIndexName, 
configWaitForActiveShards, configSize, configFrom);
 
             switch (operation) {
                 case Index: {
@@ -455,6 +460,12 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
             if (ctx.isConfigWaitForActiveShards()) {
                 
message.removeHeader(ElasticsearchConstants.PARAM_WAIT_FOR_ACTIVE_SHARDS);
             }
+            if (ctx.isConfigSize()) {
+                message.removeHeader(ElasticsearchConstants.PARAM_SIZE);
+            }
+            if (ctx.isConfigFrom()) {
+                message.removeHeader(ElasticsearchConstants.PARAM_FROM);
+            }
             if (configuration.isDisconnect()) {
                 IOHelper.close(ctx.getTransport());
                 if (configuration.isEnableSniffer()) {
@@ -586,14 +597,18 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
         private final ElasticsearchTransport transport;
         private final boolean configIndexName;
         private final boolean configWaitForActiveShards;
+        private final boolean configSize;
+        private final boolean configFrom;
 
         ActionContext(Exchange exchange, AsyncCallback callback, 
ElasticsearchTransport transport, boolean configIndexName,
-                      boolean configWaitForActiveShards) {
+                      boolean configWaitForActiveShards, boolean configSize, 
boolean configFrom) {
             this.exchange = exchange;
             this.callback = callback;
             this.transport = transport;
             this.configIndexName = configIndexName;
             this.configWaitForActiveShards = configWaitForActiveShards;
+            this.configSize = configSize;
+            this.configFrom = configFrom;
         }
 
         ElasticsearchTransport getTransport() {
@@ -612,6 +627,14 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
             return configWaitForActiveShards;
         }
 
+        boolean isConfigSize() {
+            return configSize;
+        }
+
+        boolean isConfigFrom() {
+            return configFrom;
+        }
+
         Exchange getExchange() {
             return exchange;
         }
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchScrollRequestIterator.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchScrollRequestIterator.java
index b4ebf0d51910..b336998609e8 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchScrollRequestIterator.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchScrollRequestIterator.java
@@ -125,11 +125,14 @@ public class 
ElasticsearchScrollRequestIterator<TDocument> implements Iterator<H
     public void close() {
         if (!closed) {
             try {
-                ClearScrollRequest clearScrollRequest = new 
ClearScrollRequest.Builder()
-                        .scrollId(List.of(scrollId))
-                        .build();
-
-                esClient.clearScroll(clearScrollRequest);
+                // scrollId can be null if the initial search returned no 
scroll id; List.of(null) would NPE
+                if (scrollId != null) {
+                    ClearScrollRequest clearScrollRequest = new 
ClearScrollRequest.Builder()
+                            .scrollId(List.of(scrollId))
+                            .build();
+
+                    esClient.clearScroll(clearScrollRequest);
+                }
                 closed = true;
                 
exchange.setProperty(ElasticsearchConstants.PROPERTY_SCROLL_ES_QUERY_COUNT, 
requestCount);
             } catch (IOException e) {
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
index 90b2fc8ff76e..7e18c719dd8e 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
@@ -85,7 +85,12 @@ public final class ElasticsearchActionRequestConverter {
     @Converter
     public static IndexRequest.Builder<?> toIndexRequestBuilder(Object 
document, Exchange exchange) throws IOException {
         if (document instanceof IndexRequest.Builder<?> indexReqBuilder) {
-            return 
indexReqBuilder.id(exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID,
 String.class));
+            // only override the id when the header is present, otherwise a 
caller-supplied id would be cleared
+            String id = 
exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID, String.class);
+            if (id != null) {
+                indexReqBuilder.id(id);
+            }
+            return indexReqBuilder;
         }
         IndexRequest.Builder<Object> builder = new IndexRequest.Builder<>();
         if (document instanceof byte[] byteArray) {
@@ -115,12 +120,17 @@ public final class ElasticsearchActionRequestConverter {
     @Converter
     public static UpdateRequest.Builder<?, ?> toUpdateRequestBuilder(Object 
document, Exchange exchange) throws IOException {
         if (document instanceof UpdateRequest.Builder<?, ?> updateReqBuilder) {
-            return 
updateReqBuilder.id(exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID,
 String.class));
+            // only override the id when the header is present, otherwise a 
caller-supplied id would be cleared
+            String id = 
exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID, String.class);
+            if (id != null) {
+                updateReqBuilder.id(id);
+            }
+            return updateReqBuilder;
         }
         UpdateRequest.Builder<?, Object> builder = new 
UpdateRequest.Builder<>();
         Boolean enableDocumentOnlyMode
                 = 
exchange.getIn().getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, 
Boolean.FALSE, Boolean.class);
-        Mode mode = enableDocumentOnlyMode == Boolean.TRUE ? 
Mode.DOCUMENT_ONLY : Mode.DEFAULT;
+        Mode mode = Boolean.TRUE.equals(enableDocumentOnlyMode) ? 
Mode.DOCUMENT_ONLY : Mode.DEFAULT;
         if (document instanceof byte[] byteArray) {
             mode.addDocToUpdateRequestBuilder(builder, new 
ByteArrayInputStream(byteArray));
         } else if (document instanceof InputStream inputStream) {
diff --git 
a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverterTest.java
 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverterTest.java
new file mode 100644
index 000000000000..796e859980b3
--- /dev/null
+++ 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverterTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.es.converter;
+
+import java.util.Map;
+
+import co.elastic.clients.elasticsearch.core.IndexRequest;
+import co.elastic.clients.elasticsearch.core.UpdateRequest;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.es.ElasticsearchConstants;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ElasticsearchActionRequestConverterTest {
+
+    private CamelContext context;
+
+    @BeforeEach
+    void setUp() {
+        context = new DefaultCamelContext();
+    }
+
+    @AfterEach
+    void tearDown() {
+        context.stop();
+    }
+
+    private IndexRequest.Builder<Object> preBuiltIndexBuilder() {
+        return new 
IndexRequest.Builder<>().index("idx").id("original").document(Map.of("k", "v"));
+    }
+
+    @Test
+    void preBuiltIndexBuilderKeepsItsIdWhenHeaderAbsent() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+
+        IndexRequest.Builder<?> result
+                = 
ElasticsearchActionRequestConverter.toIndexRequestBuilder(preBuiltIndexBuilder(),
 exchange);
+
+        // no CamelIndexId header -> the caller's id must be preserved, not 
overwritten with null
+        assertEquals("original", result.build().id());
+    }
+
+    @Test
+    void preBuiltIndexBuilderHeaderOverridesId() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setHeader(ElasticsearchConstants.PARAM_INDEX_ID, 
"fromHeader");
+
+        IndexRequest.Builder<?> result
+                = 
ElasticsearchActionRequestConverter.toIndexRequestBuilder(preBuiltIndexBuilder(),
 exchange);
+
+        assertEquals("fromHeader", result.build().id());
+    }
+
+    @Test
+    void preBuiltUpdateBuilderKeepsItsIdWhenHeaderAbsent() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        UpdateRequest.Builder<Object, Object> preBuilt
+                = new 
UpdateRequest.Builder<>().index("idx").id("original").doc(Map.of("k", "v"));
+
+        UpdateRequest.Builder<?, ?> result
+                = 
ElasticsearchActionRequestConverter.toUpdateRequestBuilder(preBuilt, exchange);
+
+        // no CamelIndexId header -> the caller's id must be preserved, not 
overwritten with null
+        assertEquals("original", result.build().id());
+    }
+}
diff --git 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchProducer.java
 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchProducer.java
index f90f6314a1ca..2d96335235bf 100644
--- 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchProducer.java
+++ 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchProducer.java
@@ -189,14 +189,18 @@ class OpensearchProducer extends DefaultAsyncProducer {
                 configIndexName = true;
             }
 
+            boolean configSize = false;
             Integer size = message.getHeader(OpensearchConstants.PARAM_SIZE, 
Integer.class);
             if (size == null) {
                 message.setHeader(OpensearchConstants.PARAM_SIZE, 
configuration.getSize());
+                configSize = true;
             }
 
+            boolean configFrom = false;
             Integer from = message.getHeader(OpensearchConstants.PARAM_FROM, 
Integer.class);
             if (from == null) {
                 message.setHeader(OpensearchConstants.PARAM_FROM, 
configuration.getFrom());
+                configFrom = true;
             }
 
             boolean configWaitForActiveShards = false;
@@ -211,7 +215,8 @@ class OpensearchProducer extends DefaultAsyncProducer {
                 documentClass = configuration.getDocumentClass();
             }
 
-            ActionContext ctx = new ActionContext(exchange, callback, 
transport, configIndexName, configWaitForActiveShards);
+            ActionContext ctx = new ActionContext(
+                    exchange, callback, transport, configIndexName, 
configWaitForActiveShards, configSize, configFrom);
 
             switch (operation) {
                 case Index -> processIndexAsync(ctx);
@@ -441,6 +446,12 @@ class OpensearchProducer extends DefaultAsyncProducer {
             if (ctx.configWaitForActiveShards()) {
                 
message.removeHeader(OpensearchConstants.PARAM_WAIT_FOR_ACTIVE_SHARDS);
             }
+            if (ctx.configSize()) {
+                message.removeHeader(OpensearchConstants.PARAM_SIZE);
+            }
+            if (ctx.configFrom()) {
+                message.removeHeader(OpensearchConstants.PARAM_FROM);
+            }
             if (configuration.isDisconnect() && openSearchClient == null) {
                 IOHelper.close(ctx.transport());
                 if (configuration.isEnableSniffer()) {
@@ -604,7 +615,7 @@ class OpensearchProducer extends DefaultAsyncProducer {
      * An inner class providing all the information that an asynchronous 
action could need.
      */
     private record ActionContext(Exchange exchange, AsyncCallback callback, 
OpenSearchTransport transport,
-            boolean configIndexName, boolean configWaitForActiveShards) {
+            boolean configIndexName, boolean configWaitForActiveShards, 
boolean configSize, boolean configFrom) {
 
         OpenSearchAsyncClient getClient() {
             return new OpenSearchAsyncClient(transport);
diff --git 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchScrollRequestIterator.java
 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchScrollRequestIterator.java
index 70e19c9c0880..5c70ac93c61c 100644
--- 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchScrollRequestIterator.java
+++ 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/OpensearchScrollRequestIterator.java
@@ -125,11 +125,14 @@ public class OpensearchScrollRequestIterator<TDocument> 
implements Iterator<Hit<
     public void close() {
         if (!closed) {
             try {
-                ClearScrollRequest clearScrollRequest = new 
ClearScrollRequest.Builder()
-                        .scrollId(List.of(scrollId))
-                        .build();
-
-                esClient.clearScroll(clearScrollRequest);
+                // scrollId can be null if the initial search returned no 
scroll id; List.of(null) would NPE
+                if (scrollId != null) {
+                    ClearScrollRequest clearScrollRequest = new 
ClearScrollRequest.Builder()
+                            .scrollId(List.of(scrollId))
+                            .build();
+
+                    esClient.clearScroll(clearScrollRequest);
+                }
                 closed = true;
                 
exchange.setProperty(OpensearchConstants.PROPERTY_SCROLL_OPENSEARCH_QUERY_COUNT,
 requestCount);
             } catch (IOException e) {
diff --git 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverter.java
 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverter.java
index 512c2aa118e8..bdb6c711ec9c 100644
--- 
a/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverter.java
+++ 
b/components/camel-opensearch/src/main/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverter.java
@@ -88,7 +88,12 @@ public final class OpensearchActionRequestConverter {
     @Converter
     public static IndexRequest.Builder<?> toIndexRequestBuilder(Object 
document, Exchange exchange) throws IOException {
         if (document instanceof IndexRequest.Builder<?> builder) {
-            return 
builder.id(exchange.getIn().getHeader(OpensearchConstants.PARAM_INDEX_ID, 
String.class));
+            // only override the id when the header is present, otherwise a 
caller-supplied id would be cleared
+            String id = 
exchange.getIn().getHeader(OpensearchConstants.PARAM_INDEX_ID, String.class);
+            if (id != null) {
+                builder.id(id);
+            }
+            return builder;
         }
         JacksonJsonpMapper mapper = createMapper();
         IndexRequest.Builder<Object> builder = new IndexRequest.Builder<>();
@@ -116,7 +121,12 @@ public final class OpensearchActionRequestConverter {
     @Converter
     public static UpdateRequest.Builder<?, ?> toUpdateRequestBuilder(Object 
document, Exchange exchange) throws IOException {
         if (document instanceof UpdateRequest.Builder<?, ?> builder) {
-            return 
builder.id(exchange.getIn().getHeader(OpensearchConstants.PARAM_INDEX_ID, 
String.class));
+            // only override the id when the header is present, otherwise a 
caller-supplied id would be cleared
+            String id = 
exchange.getIn().getHeader(OpensearchConstants.PARAM_INDEX_ID, String.class);
+            if (id != null) {
+                builder.id(id);
+            }
+            return builder;
         }
         JacksonJsonpMapper mapper = createMapper();
         UpdateRequest.Builder<?, Object> builder = new 
UpdateRequest.Builder<>();
diff --git 
a/components/camel-opensearch/src/test/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverterTest.java
 
b/components/camel-opensearch/src/test/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverterTest.java
new file mode 100644
index 000000000000..87dede478c7d
--- /dev/null
+++ 
b/components/camel-opensearch/src/test/java/org/apache/camel/component/opensearch/converter/OpensearchActionRequestConverterTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.opensearch.converter;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.opensearch.OpensearchConstants;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.opensearch.client.opensearch.core.IndexRequest;
+import org.opensearch.client.opensearch.core.UpdateRequest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class OpensearchActionRequestConverterTest {
+
+    private CamelContext context;
+
+    @BeforeEach
+    void setUp() {
+        context = new DefaultCamelContext();
+    }
+
+    @AfterEach
+    void tearDown() {
+        context.stop();
+    }
+
+    private IndexRequest.Builder<Object> preBuiltIndexBuilder() {
+        return new 
IndexRequest.Builder<>().index("idx").id("original").document(Map.of("k", "v"));
+    }
+
+    @Test
+    void preBuiltIndexBuilderKeepsItsIdWhenHeaderAbsent() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+
+        IndexRequest.Builder<?> result
+                = 
OpensearchActionRequestConverter.toIndexRequestBuilder(preBuiltIndexBuilder(), 
exchange);
+
+        // no CamelOpensearchIndexId header -> the caller's id must be 
preserved, not overwritten with null
+        assertEquals("original", result.build().id());
+    }
+
+    @Test
+    void preBuiltIndexBuilderHeaderOverridesId() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setHeader(OpensearchConstants.PARAM_INDEX_ID, 
"fromHeader");
+
+        IndexRequest.Builder<?> result
+                = 
OpensearchActionRequestConverter.toIndexRequestBuilder(preBuiltIndexBuilder(), 
exchange);
+
+        assertEquals("fromHeader", result.build().id());
+    }
+
+    @Test
+    void preBuiltUpdateBuilderKeepsItsIdWhenHeaderAbsent() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        UpdateRequest.Builder<Object, Object> preBuilt
+                = new 
UpdateRequest.Builder<>().index("idx").id("original").doc(Map.of("k", "v"));
+
+        UpdateRequest.Builder<?, ?> result
+                = 
OpensearchActionRequestConverter.toUpdateRequestBuilder(preBuilt, exchange);
+
+        // no CamelOpensearchIndexId header -> the caller's id must be 
preserved, not overwritten with null
+        assertEquals("original", result.build().id());
+    }
+}

Reply via email to