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

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


The following commit(s) were added to refs/heads/camel-4.18.x by this push:
     new 1a7c6f41d540 [backport camel-4.18.x] CAMEL-26028: camel-support - the 
error of a failed API component call names its arguments, without their values 
(#28420)
1a7c6f41d540 is described below

commit 1a7c6f41d540a039d7dbcee9fc02c6349b8d13ad
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Oct 25 08:41:41 2026 +0100

    [backport camel-4.18.x] CAMEL-26028: camel-support - the error of a failed 
API component call names its arguments, without their values (#28420)
    
    Signed-off-by: Claus Ibsen <[email protected]>
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../support/component/ApiMethodHelperTest.java     | 26 ++++++++++++++++++
 .../camel/support/component/ApiMethodHelper.java   | 32 ++++++++++++++++++++--
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git 
a/core/camel-core/src/test/java/org/apache/camel/support/component/ApiMethodHelperTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/support/component/ApiMethodHelperTest.java
index cac6e63b9f07..2a658a78268c 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/support/component/ApiMethodHelperTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/support/component/ApiMethodHelperTest.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.camel.RuntimeCamelException;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.camel.support.component.ApiMethodArg.arg;
@@ -189,6 +190,31 @@ public class ApiMethodHelperTest {
         assertEquals("Howdy Dave", ApiMethodHelper.invokeMethod(proxy, 
TestMethod.SAYHI_1, properties), "Derived sayHi(name)");
     }
 
+    @Test
+    public void testInvokeMethodErrorShowsNoArgumentValues() {
+        // the arguments hold the endpoint options, such as a password, and 
the message data
+        TestProxy proxy = new TestProxy() {
+            @Override
+            public String sayHi(String name) {
+                throw new IllegalStateException("boom");
+            }
+        };
+        final Map<String, Object> properties = new HashMap<>();
+        properties.put("name", "Dave");
+        properties.put("password", "Secret123");
+
+        RuntimeCamelException e = assertThrows(RuntimeCamelException.class,
+                () -> ApiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, 
properties));
+        assertEquals("Error invoking sayHi with [name, password]: boom", 
e.getMessage());
+
+        // an argument of the wrong type fails in the invocation itself
+        properties.put("name", 42);
+        e = assertThrows(RuntimeCamelException.class,
+                () -> ApiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, 
properties));
+        assertTrue(e.getMessage().startsWith("Error invoking sayHi with [name, 
password]: "), e.getMessage());
+        assertFalse(e.getMessage().contains("Secret123"), e.getMessage());
+    }
+
     enum TestMethod implements ApiMethod {
 
         SAYHI(String.class, "sayHi"),
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/component/ApiMethodHelper.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/component/ApiMethodHelper.java
index 48578e162d8e..3bc4bac6274e 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/component/ApiMethodHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/component/ApiMethodHelper.java
@@ -26,11 +26,14 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.SensitiveUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -475,7 +478,7 @@ public final class ApiMethodHelper<T extends Enum<T> & 
ApiMethod> {
             throws RuntimeCamelException {
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("Invoking {} with arguments {}", method.getName(), 
properties);
+            LOG.debug("Invoking {} with arguments {}", method.getName(), 
masked(properties));
         }
 
         final List<String> argNames = method.getArgNames();
@@ -530,14 +533,37 @@ public final class ApiMethodHelper<T extends Enum<T> & 
ApiMethod> {
             String message = cause != null ? cause.getMessage() : 
e.getMessage();
 
             throw new RuntimeCamelException(
-                    String.format("Error invoking %s with %s: %s", 
method.getName(), properties, message),
+                    String.format("Error invoking %s with %s: %s", 
method.getName(), names(properties), message),
                     cause != null ? cause : e);
         } catch (Exception e) {
             throw new RuntimeCamelException(
-                    String.format("Error invoking %s with %s: %s", 
method.getName(), properties, e.getMessage()), e);
+                    String.format("Error invoking %s with %s: %s", 
method.getName(), names(properties), e.getMessage()), e);
         }
     }
 
+    /**
+     * The names of the arguments, for an error message: their values hold the 
endpoint options, such as a password, and
+     * the message data, which an error message must not show.
+     */
+    private static Set<String> names(Map<String, Object> properties) {
+        return new TreeSet<>(properties.keySet());
+    }
+
+    /**
+     * The arguments with the values of the sensitive options masked, such as 
a password or a token, for the debug log.
+     */
+    private static Map<String, Object> masked(Map<String, Object> properties) {
+        Map<String, Object> answer = new TreeMap<>();
+        for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            Object value = entry.getValue();
+            if (SensitiveUtils.containsSensitive(entry.getKey())) {
+                value = "xxxxxx";
+            }
+            answer.put(entry.getKey(), value);
+        }
+        return answer;
+    }
+
     public enum MatchType {
         EXACT,
         SUBSET,

Reply via email to