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 15f193253391 CAMEL-25322: camel-bean - a missing Map key says the Map 
has no such key and lists its keys (#27334)
15f193253391 is described below

commit 15f193253391b894f104ebef2d02ea3ed5df8ad9
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Oct 4 16:34:30 2026 +0200

    CAMEL-25322: camel-bean - a missing Map key says the Map has no such key 
and lists its keys (#27334)
    
    Since CAMEL-24916 ${body.orderId} on a Map reads the key, so failing there
    means the key is missing. The hint still said "a key is read with [orderId],
    as in ${body[orderId]}, not with .orderId", which points the wrong way: the
    dot is fine and the bracket form gives null. It now says "the Map has no key
    orderId; its keys are: sku, qty, price" (at most 20 keys listed), or that
    the Map is empty. The usual cause shows at once: inside a split over an
    order's lines the body is a line, not the order.
    
    
    Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../org/apache/camel/language/bean/BeanExpression.java | 18 +++++++++++++-----
 .../camel/language/simple/SimpleSyntaxHintsTest.java   | 12 +++++++++++-
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git 
a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
 
b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
index 4be7cc3187cc..8be103fe316a 100644
--- 
a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
+++ 
b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java
@@ -18,6 +18,7 @@ package org.apache.camel.language.bean;
 
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.apache.camel.BeanScope;
 import org.apache.camel.CamelContext;
@@ -580,9 +581,13 @@ public class BeanExpression implements Expression, 
Predicate {
         return NO_SUCH_KEY;
     }
 
+    /** At most this many keys are listed when a Map has no key of the name 
asked for. */
+    private static final int MAX_KEYS_LISTED = 20;
+
     /**
-     * ${body.type} on a Map body looks for a method named type; a key is read 
with ${body[type]}. Say so when the bean
-     * is a Map and the name is not a method call.
+     * ${body.type} on a Map body reads the key type (CAMEL-24916), so getting 
here means the Map has no such key: say
+     * that and list its keys, since the usual cause is a body that is not the 
Map one thinks (inside a split over an
+     * order's lines the body is a line, not the order) (CAMEL-25322).
      */
     private static String keyHint(BeanHolder holder, Exchange exchange, String 
methodName, String hint) {
         if (methodName == null || methodName.contains("(") || 
methodName.contains("[")) {
@@ -590,9 +595,12 @@ public class BeanExpression implements Expression, 
Predicate {
         }
         try {
             Object bean = holder != null ? holder.getBean(exchange) : null;
-            if (bean instanceof Map) {
-                return hint + " (the value is a Map: a key is read with [" + 
methodName + "], as in ${body[" + methodName
-                       + "]}, not with ." + methodName + ")";
+            if (bean instanceof Map<?, ?> map) {
+                String keys = 
map.keySet().stream().limit(MAX_KEYS_LISTED).map(String::valueOf)
+                        .collect(Collectors.joining(", "));
+                String more = map.size() > MAX_KEYS_LISTED ? ", ... (" + 
map.size() + " keys)" : "";
+                return hint + " (the Map has no key " + methodName
+                       + (map.isEmpty() ? "; it is empty)" : "; its keys are: 
" + keys + more + ")");
             }
         } catch (Exception e) {
             // ignore
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleSyntaxHintsTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleSyntaxHintsTest.java
index 55de40810c70..63f8520cc954 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleSyntaxHintsTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleSyntaxHintsTest.java
@@ -177,7 +177,17 @@ public class SimpleSyntaxHintsTest extends 
ExchangeTestSupport {
         Exception e = assertThrows(Exception.class,
                 () -> 
context.resolveLanguage("simple").createExpression("${body.typo}").evaluate(exchange,
                         String.class));
-        assertThat(e.getMessage()).contains("the value is a Map: a key is read 
with [typo], as in ${body[typo]}");
+        // CAMEL-25322: the dot reads a key, so the hint says the key is 
missing and which keys there are
+        assertThat(e.getMessage()).contains("(the Map has no key typo; its 
keys are: type)");
+    }
+
+    @Test
+    public void testOgnlDotOnAnEmptyMapSaysItIsEmpty() {
+        exchange.getIn().setBody(new java.util.LinkedHashMap<>());
+        Exception e = assertThrows(Exception.class,
+                () -> 
context.resolveLanguage("simple").createExpression("${body.orderId}").evaluate(exchange,
+                        String.class));
+        assertThat(e.getMessage()).contains("(the Map has no key orderId; it 
is empty)");
     }
 
     @Test

Reply via email to