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

davsclaus pushed a commit to branch CAMEL-26512-spring-ai-embeddings-text-body
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 238ebe6782a88f4f3513def4991060ed7708644f
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Nov 3 15:42:56 2026 +0100

    CAMEL-26512: camel-spring-ai-embeddings - fail a Map or POJO body, or List 
element, instead of embedding its toString()
    
    A body, and each element of a List body, was converted to a String with the 
type converter, so a Map,
    a POJO or a number went through the ToString fallback converter and was 
embedded as its toString(),
    such as {a=1, b=2}. A Spring AI Document was embedded as its toString() 
too. Now text, bytes, a stream,
    a Reader or a file is read as text, a Document is embedded as its text, and 
any other value fails with
    an InvalidPayloadException that says to convert the body to text first (for 
a List element, the
    message names its index and type), as in the langchain4j embeddings 
components. The body types no
    longer list any body, and the upgrade guide notes the change.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../catalog/components/spring-ai-embeddings.json   |   2 +-
 .../docs/spring-ai-embeddings-component.adoc       |   5 +-
 .../springai/embeddings/spring-ai-embeddings.json  |   2 +-
 .../main/docs/spring-ai-embeddings-component.adoc  |   5 +-
 .../embeddings/SpringAiEmbeddingsEndpoint.java     |   9 +-
 .../embeddings/SpringAiEmbeddingsProducer.java     |  73 +++++++++++---
 .../SpringAiEmbeddingsComponentTest.java           | 111 ++++++++++++++++++++-
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  13 ++-
 8 files changed, 188 insertions(+), 32 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-ai-embeddings.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-ai-embeddings.json
index e182c253f1ef..fe27c5cab2a7 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-ai-embeddings.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-ai-embeddings.json
@@ -38,7 +38,7 @@
     "CamelSpringAiEmbeddingInputTexts": { "index": 5, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "java.util.List<String>", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "List of input texts 
that were embedded", "constantName": 
"org.apache.camel.component.springai.embeddings.SpringAiEmbeddingsHeaders#INPUT_TEXTS"
 }
   },
   "bodyTypes": {
-    "producerIn": { "carriers": [ "any" ], "description": "The text to embed, 
or a List of texts for a batch. Another body, and each element of a List, is 
converted to text (a Map or a POJO as its toString()); no body, or a null 
element in a List, fails" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], 
"description": "The text to embed: a String, bytes, a stream or a file read as 
text, or a Spring AI Document as its text; or a List of them for a batch. 
Another body or List element, such as a Map or a POJO, fails, as do no body and 
a null element: convert it to text first" },
     "producerOut": { "carriers": [ "list" ], "description": "The vector as a 
float[] for one text, and a List of float[] for a List of texts, also for a 
List with one text or none. The Embedding and the input text are in headers, 
which spring-ai-vector-store reads" }
   },
   "properties": {
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spring-ai-embeddings-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spring-ai-embeddings-component.adoc
index 99ab8537b98c..ffb8a829229c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spring-ai-embeddings-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/spring-ai-embeddings-component.adoc
@@ -50,7 +50,10 @@ The component accepts two types of input:
 * **Single text**: A String containing the text to embed
 * **Batch processing**: A List<String> containing multiple texts to embed at 
once
 
-Another body, and each element of a List, is converted to a String. A `null` 
element in a List fails the exchange
+Bytes, a stream, a `Reader` or a file is read as text, and a Spring AI 
`Document` is embedded as its text, as a body
+and as an element of a List. Any other body or List element, such as a `Map`, 
a POJO or a number, fails the exchange
+with an `InvalidPayloadException` instead of being embedded as its 
`toString()`: turn it into text first, with
+`convertBodyTo(String.class)` or a marshal to JSON, say. No body, or a `null` 
element in a List, fails the exchange
 with an `IllegalArgumentException`.
 
 The embedding vectors are returned in the message body, with additional 
metadata available in headers.
diff --git 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/generated/resources/META-INF/org/apache/camel/component/springai/embeddings/spring-ai-embeddings.json
 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/generated/resources/META-INF/org/apache/camel/component/springai/embeddings/spring-ai-embeddings.json
index e182c253f1ef..fe27c5cab2a7 100644
--- 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/generated/resources/META-INF/org/apache/camel/component/springai/embeddings/spring-ai-embeddings.json
+++ 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/generated/resources/META-INF/org/apache/camel/component/springai/embeddings/spring-ai-embeddings.json
@@ -38,7 +38,7 @@
     "CamelSpringAiEmbeddingInputTexts": { "index": 5, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "java.util.List<String>", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "description": "List of input texts 
that were embedded", "constantName": 
"org.apache.camel.component.springai.embeddings.SpringAiEmbeddingsHeaders#INPUT_TEXTS"
 }
   },
   "bodyTypes": {
-    "producerIn": { "carriers": [ "any" ], "description": "The text to embed, 
or a List of texts for a batch. Another body, and each element of a List, is 
converted to text (a Map or a POJO as its toString()); no body, or a null 
element in a List, fails" },
+    "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], 
"description": "The text to embed: a String, bytes, a stream or a file read as 
text, or a Spring AI Document as its text; or a List of them for a batch. 
Another body or List element, such as a Map or a POJO, fails, as do no body and 
a null element: convert it to text first" },
     "producerOut": { "carriers": [ "list" ], "description": "The vector as a 
float[] for one text, and a List of float[] for a List of texts, also for a 
List with one text or none. The Embedding and the input text are in headers, 
which spring-ai-vector-store reads" }
   },
   "properties": {
diff --git 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc
 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc
index 99ab8537b98c..ffb8a829229c 100644
--- 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc
+++ 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc
@@ -50,7 +50,10 @@ The component accepts two types of input:
 * **Single text**: A String containing the text to embed
 * **Batch processing**: A List<String> containing multiple texts to embed at 
once
 
-Another body, and each element of a List, is converted to a String. A `null` 
element in a List fails the exchange
+Bytes, a stream, a `Reader` or a file is read as text, and a Spring AI 
`Document` is embedded as its text, as a body
+and as an element of a List. Any other body or List element, such as a `Map`, 
a POJO or a number, fails the exchange
+with an `InvalidPayloadException` instead of being embedded as its 
`toString()`: turn it into text first, with
+`convertBodyTo(String.class)` or a marshal to JSON, say. No body, or a `null` 
element in a List, fails the exchange
 with an `IllegalArgumentException`.
 
 The embedding vectors are returned in the message body, with additional 
metadata available in headers.
diff --git 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsEndpoint.java
 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsEndpoint.java
index e82a65c38365..e6884420db36 100644
--- 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsEndpoint.java
+++ 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsEndpoint.java
@@ -37,10 +37,11 @@ import org.apache.camel.support.DefaultEndpoint;
              syntax = "spring-ai-embeddings:embeddingId", producerOnly = true, 
category = {
                      Category.AI
              }, headersClass = SpringAiEmbeddingsHeaders.class)
-@BodyTypes(producerIn = @BodyType(value = Carrier.ANY,
-                                  description = "The text to embed, or a List 
of texts for a batch. Another body, and"
-                                                + " each element of a List, is 
converted to text (a Map or a POJO as its"
-                                                + " toString()); no body, or a 
null element in a List, fails"),
+@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.LIST },
+                                  description = "The text to embed: a String, 
bytes, a stream or a file read as text, or a"
+                                                + " Spring AI Document as its 
text; or a List of them for a batch. Another"
+                                                + " body or List element, such 
as a Map or a POJO, fails, as do no body and"
+                                                + " a null element: convert it 
to text first"),
            producerOut = @BodyType(value = Carrier.LIST,
                                    description = "The vector as a float[] for 
one text, and a List of float[] for a List"
                                                  + " of texts, also for a List 
with one text or none. The Embedding and"
diff --git 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsProducer.java
 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsProducer.java
index a3a64b8710ea..c5cc48693336 100644
--- 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsProducer.java
+++ 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsProducer.java
@@ -16,12 +16,23 @@
  */
 package org.apache.camel.component.springai.embeddings;
 
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.StreamCache;
+import org.apache.camel.WrappedFile;
 import org.apache.camel.support.DefaultProducer;
+import org.springframework.ai.document.Document;
 import org.springframework.ai.embedding.Embedding;
 import org.springframework.ai.embedding.EmbeddingModel;
 import org.springframework.ai.embedding.EmbeddingOptions;
@@ -43,7 +54,7 @@ public class SpringAiEmbeddingsProducer extends 
DefaultProducer {
         final Message message = exchange.getMessage();
         final EmbeddingModel model = 
getEndpoint().getConfiguration().getEmbeddingModel();
 
-        // Support both single String and List<String> as input
+        // Support a single text and a List of texts as input
         List<String> inputTexts;
         Object body = message.getBody();
         boolean batch = body instanceof List;
@@ -52,14 +63,10 @@ public class SpringAiEmbeddingsProducer extends 
DefaultProducer {
             inputTexts = new ArrayList<>(list.size());
             for (int i = 0; i < list.size(); i++) {
                 Object element = list.get(i);
-                String text = element != null
-                        ? 
exchange.getContext().getTypeConverter().convertTo(String.class, exchange, 
element) : null;
-                if (text == null) {
-                    throw new IllegalArgumentException(
-                            "Element " + i + " of the List body must be text, 
but was: "
-                                                       + (element != null ? 
element.getClass().getName() : "null"));
+                if (element == null) {
+                    throw new IllegalArgumentException("Element " + i + " of 
the List body must be text, but was: null");
                 }
-                inputTexts.add(text);
+                inputTexts.add(toText(exchange, element, i));
             }
             if (inputTexts.isEmpty()) {
                 // nothing to embed, so do not call the model
@@ -69,14 +76,10 @@ public class SpringAiEmbeddingsProducer extends 
DefaultProducer {
                 return;
             }
         } else {
-            String str = message.getBody(String.class);
-            if (str != null) {
-                inputTexts = List.of(str);
-            } else {
-                throw new IllegalArgumentException(
-                        "Message body must be a String or List<String>, but 
was: "
-                                                   + (body != null ? 
body.getClass().getName() : "null"));
+            if (body == null) {
+                throw new IllegalArgumentException("Message body must be a 
String or List<String>, but was: null");
             }
+            inputTexts = List.of(toText(exchange, body, -1));
         }
 
         final EmbeddingResponse response = model.call(new EmbeddingRequest(
@@ -109,4 +112,44 @@ public class SpringAiEmbeddingsProducer extends 
DefaultProducer {
             message.setHeader(SpringAiEmbeddingsHeaders.EMBEDDING_METADATA, 
response.getMetadata());
         }
     }
+
+    /**
+     * The text to embed of a body, or of an element of a List body: a Spring 
AI Document as its text, and text, bytes,
+     * a stream, a Reader or a file read as text. Any other value, such as a 
Map or a POJO, fails as an
+     * InvalidPayloadException instead of being embedded as its toString().
+     *
+     * @param index the index of the element in a List body, or -1 for the 
body itself
+     */
+    private static String toText(Exchange exchange, Object value, int index)
+            throws InvalidPayloadException, NoTypeConversionAvailableException 
{
+        String what = index < 0 ? "" : "the element at index " + index + " of 
the List body is " + typeOf(value) + "; ";
+        if (value instanceof Document document) {
+            if (document.getText() == null) {
+                throw new InvalidPayloadException(
+                        exchange, String.class, exchange.getMessage(),
+                        what + "spring-ai-embeddings embeds the text of a 
Document, but the Document has no text");
+            }
+            return document.getText();
+        }
+        if (!isReadableAsText(value)) {
+            throw new InvalidPayloadException(
+                    exchange, String.class, exchange.getMessage(),
+                    what + "spring-ai-embeddings embeds text, bytes, a stream, 
a Reader, a file or a Spring AI Document;"
+                                                                   + " convert 
the body to text before the endpoint, such"
+                                                                   + " as with 
convertBodyTo(String) or a marshal to JSON");
+        }
+        return 
exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class, 
exchange, value);
+    }
+
+    /** A value Camel converts to its text, rather than to the toString() of 
an object. */
+    private static boolean isReadableAsText(Object value) {
+        return value instanceof CharSequence || value instanceof byte[] || 
value instanceof ByteBuffer
+                || value instanceof InputStream || value instanceof Reader || 
value instanceof StreamCache
+                || value instanceof ByteArrayOutputStream
+                || value instanceof File || value instanceof Path || value 
instanceof WrappedFile;
+    }
+
+    private static String typeOf(Object value) {
+        return value == null ? "null" : value.getClass().getName();
+    }
 }
diff --git 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/test/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsComponentTest.java
 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/test/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsComponentTest.java
index 61472572c4a4..fb2ffc0995b6 100644
--- 
a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/test/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsComponentTest.java
+++ 
b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/test/java/org/apache/camel/component/springai/embeddings/SpringAiEmbeddingsComponentTest.java
@@ -16,22 +16,29 @@
  */
 package org.apache.camel.component.springai.embeddings;
 
+import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.test.junit6.CamelTestSupport;
 import org.junit.jupiter.api.Test;
+import org.springframework.ai.content.Media;
 import org.springframework.ai.document.Document;
 import org.springframework.ai.embedding.Embedding;
 import org.springframework.ai.embedding.EmbeddingModel;
 import org.springframework.ai.embedding.EmbeddingRequest;
 import org.springframework.ai.embedding.EmbeddingResponse;
 import org.springframework.ai.embedding.EmbeddingResponseMetadata;
+import org.springframework.util.MimeTypeUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -157,15 +164,96 @@ public class SpringAiEmbeddingsComponentTest extends 
CamelTestSupport {
     }
 
     @Test
-    public void testListOfNonStringsIsConvertedToText() {
+    public void testListOfTextCarriersIsConvertedToText() {
         Message result = fluentTemplate.to("spring-ai-embeddings:convert")
-                .withBody(List.of(42, new StringBuilder("hello")))
+                .withBody(List.of(new StringBuilder("hello"), 
"bytes".getBytes(StandardCharsets.UTF_8),
+                        new Document("document text")))
                 .request(Message.class);
 
-        assertThat(requests).containsExactly(List.of("42", "hello"));
+        assertThat(requests).containsExactly(List.of("hello", "bytes", 
"document text"));
         List<float[]> vectors = result.getBody(List.class);
-        assertThat(vectors).hasSize(2);
-        assertThat(result.getHeader(SpringAiEmbeddingsHeaders.INPUT_TEXTS, 
List.class)).containsExactly("42", "hello");
+        assertThat(vectors).hasSize(3);
+        assertThat(result.getHeader(SpringAiEmbeddingsHeaders.INPUT_TEXTS, 
List.class))
+                .containsExactly("hello", "bytes", "document text");
+    }
+
+    @Test
+    public void testDocumentBodyEmbedsItsText() {
+        Message result = fluentTemplate.to("spring-ai-embeddings:document")
+                .withBody(new Document("document text", Map.of("source", 
"test")))
+                .request(Message.class);
+
+        assertThat(requests).containsExactly(List.of("document text"));
+        assertThat(result.getBody(float[].class)).containsExactly(0.1f, 0.2f, 
0.3f, 0.4f, 0.5f);
+        
assertThat(result.getHeader(SpringAiEmbeddingsHeaders.INPUT_TEXT)).isEqualTo("document
 text");
+    }
+
+    @Test
+    public void testDocumentWithoutTextFails() {
+        Document media = new Document(
+                new Media(MimeTypeUtils.IMAGE_PNG, 
URI.create("https://example.com/image.png";)),
+                Map.of());
+        Exchange exchange = template.send("spring-ai-embeddings:media", e -> 
e.getMessage().setBody(media));
+
+        assertThat(exchange.getException())
+                .isInstanceOf(InvalidPayloadException.class)
+                .hasMessageContaining("the Document has no text");
+        assertThat(requests).isEmpty();
+    }
+
+    @Test
+    public void testStreamBodyIsReadAsText() {
+        Message result = fluentTemplate.to("spring-ai-embeddings:stream")
+                .withBody(new ByteArrayInputStream("streamed 
text".getBytes(StandardCharsets.UTF_8)))
+                .request(Message.class);
+
+        assertThat(requests).containsExactly(List.of("streamed text"));
+        
assertThat(result.getHeader(SpringAiEmbeddingsHeaders.INPUT_TEXT)).isEqualTo("streamed
 text");
+    }
+
+    @Test
+    public void testMapBodyFails() {
+        Exchange exchange = template.send("spring-ai-embeddings:map",
+                e -> e.getMessage().setBody(Map.of("a", 1)));
+
+        assertThat(exchange.getException())
+                .isInstanceOf(InvalidPayloadException.class)
+                .hasMessageContaining("convert the body to text before the 
endpoint");
+        assertThat(requests).isEmpty();
+    }
+
+    @Test
+    public void testPojoBodyFails() {
+        Exchange exchange = template.send("spring-ai-embeddings:pojo",
+                e -> e.getMessage().setBody(new Pojo("hello")));
+
+        assertThat(exchange.getException())
+                .isInstanceOf(InvalidPayloadException.class)
+                .hasMessageContaining("convert the body to text before the 
endpoint");
+        assertThat(requests).isEmpty();
+    }
+
+    @Test
+    public void testListWithMapElementFails() {
+        Exchange exchange = template.send("spring-ai-embeddings:listmap",
+                e -> e.getMessage().setBody(List.of("hello", Map.of("a", 1))));
+
+        assertThat(exchange.getException())
+                .isInstanceOf(InvalidPayloadException.class)
+                .hasMessageContaining("the element at index 1 of the List body 
is java.util.")
+                .hasMessageContaining("convert the body to text before the 
endpoint");
+        assertThat(requests).isEmpty();
+    }
+
+    @Test
+    public void testListWithNumberElementFails() {
+        Exchange exchange = template.send("spring-ai-embeddings:listnumber",
+                e -> e.getMessage().setBody(List.of("hello", 42)));
+
+        assertThat(exchange.getException())
+                .isInstanceOf(InvalidPayloadException.class)
+                .hasMessageContaining("the element at index 1 of the List body 
is java.lang.Integer");
+        assertThat(requests).isEmpty();
     }
 
     @Test
@@ -191,4 +279,17 @@ public class SpringAiEmbeddingsComponentTest extends 
CamelTestSupport {
         assertThat(result.getHeader(SpringAiEmbeddingsHeaders.INPUT_TEXTS, 
List.class)).isEmpty();
         assertThat(requests).isEmpty();
     }
+
+    private static final class Pojo {
+        private final String text;
+
+        Pojo(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return "Pojo[text=" + text + "]";
+        }
+    }
 }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 7c82ebd18930..df3f57e15866 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -975,16 +975,21 @@ stream failed after part of the request had already been 
sent.
 The JSON of the event is now written before the request is sent, with a 
`Content-Length` instead of a chunked request
 body. A body or a header that cannot be written as JSON fails the exchange 
without sending anything to Splunk.
 
-=== camel-spring-ai-embeddings - a List body always gives a List of vectors
+=== camel-spring-ai-embeddings - a List body always gives a List of vectors, 
and a Map or POJO body fails
 
 A `List` body with one text now gives a `List<float[]>` with one vector, as a 
`List` of more texts does, and sets the
 `CamelSpringAiEmbeddings` and `CamelSpringAiEmbeddingInputTexts` headers. 
Before, it gave a single `float[]` and set the
 `CamelSpringAiEmbedding`, `CamelSpringAiEmbeddingIndex` and 
`CamelSpringAiEmbeddingInputText` headers, as for a `String`
 body. A `String` body still gives a single `float[]`.
 
-Each element of a `List` body is now converted to a `String`, and a `null` 
element fails with an
-`IllegalArgumentException`. Before, a `List` of other objects failed with a 
`ClassCastException` in the embedding
-model. An empty `List` now gives an empty `List` without calling the embedding 
model.
+Each element of a `List` body is now read as text, and a `null` element fails 
with an `IllegalArgumentException`.
+Before, a `List` of other objects failed with a `ClassCastException` in the 
embedding model. An empty `List` now gives
+an empty `List` without calling the embedding model.
+
+The body, and each element of a `List` body, must now be text, bytes, a 
stream, a `Reader`, a file or a Spring AI
+`Document` (its text is embedded). Any other value, such as a `Map`, a POJO or 
a number, fails the exchange with an
+`InvalidPayloadException`. Before, such a body was embedded as its 
`toString()`, for example `{a=1, b=2}`, and a
+`Document` too. Convert the body to text before the endpoint, with 
`convertBodyTo(String.class)` or a marshal to JSON.
 
 === camel-spring-ai-vector-store - DELETE takes the ids from the body first, 
and the embeddings headers go with a vector body
 

Reply via email to