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

jamesnetherton pushed a commit to branch camel-quarkus-main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus-examples.git


The following commit(s) were added to refs/heads/camel-quarkus-main by this 
push:
     new da6351b1 Marshal the data-extract-langchain4j POJO store response with 
Jackson
da6351b1 is described below

commit da6351b11f39ba5f517fe1f388d8362bb52e367a
Author: James Netherton <[email protected]>
AuthorDate: Fri Aug 7 07:12:14 2026 +0100

    Marshal the data-extract-langchain4j POJO store response with Jackson
    
    CustomPojoStore.asString() hand-built its JSON response by concatenating
    CustomPojo.toString() values, and that toString() was itself a String.format
    into a JSON-shaped template. The interpolated values are LLM output, so a
    single quote or backslash in a model response makes /custom-pojo-store serve
    malformed JSON.
    
    The store now returns the CustomPojo objects and the route marshals them 
with
    .marshal().json(JsonLibrary.Jackson). CustomPojo.toString() stays
    human-readable for the log line, but no longer pretends to be JSON.
    
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
 data-extract-langchain4j/README.adoc                   |  8 +-------
 data-extract-langchain4j/pom.xml                       |  4 ++++
 .../acme/extraction/CustomPojoExtractionService.java   |  8 ++------
 .../main/java/org/acme/extraction/CustomPojoStore.java | 10 +++-------
 .../java/org/acme/extraction/DataExtractAgent.java     |  2 +-
 .../src/main/java/org/acme/extraction/Routes.java      |  4 +++-
 .../src/test/java/org/acme/extraction/RouteTest.java   | 18 ++++++++++++------
 7 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/data-extract-langchain4j/README.adoc 
b/data-extract-langchain4j/README.adoc
index c04ca193..6f3cafe9 100644
--- a/data-extract-langchain4j/README.adoc
+++ b/data-extract-langchain4j/README.adoc
@@ -99,13 +99,7 @@ At the end, we are provided with a Plain Old Java Object 
(POJO) handling the ext
 
 [source,shell]
 ----
-2026-05-27 18:31:55,373 INFO  [org.acme.extraction.CustomPojoStore] (Camel 
(camel-1) thread #1 - file://target/transcripts) An extracted POJO has been 
added to the store: 
-{
-    "customerSatisfied": "true",
-    "customerName": "Sarah London",
-    "customerBirthday": "10 JULY 1986",
-    "summary": "The customer, Sarah London, called to declare an accident on 
her main vehicle. The operator confirmed that all expenses related to the 
accident will be reimbursed."
-}
+2026-05-27 18:31:55,373 INFO  [org.acme.extraction.CustomPojoStore] (Camel 
(camel-1) thread #1 - file://target/transcripts) An extracted POJO has been 
added to the store: CustomPojo[customerSatisfied=true, customerName=Sarah 
London, customerBirthday=10 JULY 1986, summary=The customer, Sarah London, 
called to declare an accident on her main vehicle. The operator confirmed that 
all expenses related to the accident will be reimbursed.]
 ----
 
 .See how the LLM shows its capacity to:
diff --git a/data-extract-langchain4j/pom.xml b/data-extract-langchain4j/pom.xml
index f489628e..eee99d90 100644
--- a/data-extract-langchain4j/pom.xml
+++ b/data-extract-langchain4j/pom.xml
@@ -88,6 +88,10 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-file</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-jackson</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-jsonpath</artifactId>
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
index c153d19b..521e2e5a 100644
--- 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
+++ 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
@@ -38,12 +38,8 @@ public interface CustomPojoExtractionService {
         @JsonProperty(required = true)
         public String summary;
 
-        private final static String FORMAT = "\n{\n"
-                + "\t\"customerSatisfied\": \"%s\",\n"
-                + "\t\"customerName\": \"%s\",\n"
-                + "\t\"customerBirthday\": \"%02d %s %04d\",\n"
-                + "\t\"summary\": \"%s\"\n"
-                + "}\n";
+        private final static String FORMAT = "CustomPojo[customerSatisfied=%s, 
customerName=%s, "
+                + "customerBirthday=%02d %s %04d, summary=%s]";
 
         public String toString() {
             return String.format(Locale.US, FORMAT, this.customerSatisfied, 
this.customerName, this.customerBirthday.day,
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoStore.java
 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoStore.java
index 0a7ab93e..4c827ef5 100644
--- 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoStore.java
+++ 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoStore.java
@@ -17,8 +17,8 @@
 package org.acme.extraction;
 
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.stream.Collectors;
 
 import jakarta.enterprise.context.ApplicationScoped;
 import org.acme.extraction.CustomPojoExtractionService.CustomPojo;
@@ -37,12 +37,8 @@ public class CustomPojoStore {
     }
 
     @Handler
-    String asString() {
-        StringBuilder sb = new StringBuilder("{ \"pojos\": [");
-        String pojoString = 
pojos.stream().map(CustomPojo::toString).collect(Collectors.joining(","));
-        sb.append(pojoString);
-        sb.append("] }");
-        return sb.toString();
+    Map<String, List<CustomPojo>> listPojos() {
+        return Map.of("pojos", List.copyOf(pojos));
     }
 
 }
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgent.java
 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgent.java
index b4de066f..8e545dc3 100644
--- 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgent.java
+++ 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgent.java
@@ -38,7 +38,7 @@ public class DataExtractAgent implements Agent {
     }
 
     /**
-     * Returns a JSON representation of a {@link CustomPojo}.
+     * Returns a string representation of the extracted {@link CustomPojo}.
      */
     @Override
     public String chat(AiAgentBody<?> aiAgentBody, ToolProvider toolProvider) {
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/Routes.java 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/Routes.java
index 1c1f3624..dd55cdde 100644
--- a/data-extract-langchain4j/src/main/java/org/acme/extraction/Routes.java
+++ b/data-extract-langchain4j/src/main/java/org/acme/extraction/Routes.java
@@ -19,6 +19,7 @@ package org.acme.extraction;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.dataformat.JsonLibrary;
 
 import static org.acme.extraction.DataExtractAgentConfiguration.AGENT_ID;
 
@@ -40,6 +41,7 @@ public class Routes extends RouteBuilder {
 
         // This route make it possible to inspect the extracted POJOs, mainly 
used for demo and test
         from("platform-http:/custom-pojo-store?produces=application/json")
-                .bean(customPojoStore);
+                .bean(customPojoStore)
+                .marshal().json(JsonLibrary.Jackson);
     }
 }
diff --git 
a/data-extract-langchain4j/src/test/java/org/acme/extraction/RouteTest.java 
b/data-extract-langchain4j/src/test/java/org/acme/extraction/RouteTest.java
index 913a34fe..f9ed4ebb 100644
--- a/data-extract-langchain4j/src/test/java/org/acme/extraction/RouteTest.java
+++ b/data-extract-langchain4j/src/test/java/org/acme/extraction/RouteTest.java
@@ -65,19 +65,25 @@ public class RouteTest {
                 .then()
                 .statusCode(200)
                 // Assert values of the first extracted POJO
-                .body("pojos[0].customerSatisfied", is("true"))
+                .body("pojos[0].customerSatisfied", is(true))
                 .body("pojos[0].customerName", is("Sarah London"))
-                .body("pojos[0].customerBirthday", is("10 JULY 1986"))
+                .body("pojos[0].customerBirthday.day", is(10))
+                .body("pojos[0].customerBirthday.month", is(7))
+                .body("pojos[0].customerBirthday.year", is(1986))
                 .body("pojos[0].summary", not(empty()))
                 // Assert values of the second extracted POJO
-                .body("pojos[1].customerSatisfied", is("false"))
+                .body("pojos[1].customerSatisfied", is(false))
                 .body("pojos[1].customerName", is("John Doe"))
-                .body("pojos[1].customerBirthday", is("01 NOVEMBER 2001"))
+                .body("pojos[1].customerBirthday.day", is(1))
+                .body("pojos[1].customerBirthday.month", is(11))
+                .body("pojos[1].customerBirthday.year", is(2001))
                 .body("pojos[1].summary", not(empty()))
                 // Assert values of the third extracted POJO
-                .body("pojos[2].customerSatisfied", is("true"))
+                .body("pojos[2].customerSatisfied", is(true))
                 .body("pojos[2].customerName", is("Kate Boss"))
-                .body("pojos[2].customerBirthday", is("13 AUGUST 1999"))
+                .body("pojos[2].customerBirthday.day", is(13))
+                .body("pojos[2].customerBirthday.month", is(8))
+                .body("pojos[2].customerBirthday.year", is(1999))
                 .body("pojos[2].summary", not(empty()));
     }
 

Reply via email to