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 4a231fecd3c3 CAMEL-25373: camel-rest - the unresolved path parameter 
warning comes back once a minute, and names an exchange property (#27426)
4a231fecd3c3 is described below

commit 4a231fecd3c3289619611c4e8cf8ef561c3a623e
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Oct 6 11:23:25 2026 +0200

    CAMEL-25373: camel-rest - the unresolved path parameter warning comes back 
once a minute, and names an exchange property (#27426)
    
    CAMEL-25373: camel-rest - the unresolved path parameter warning comes back 
once a minute, and names an exchange property of that name
    
    
    Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../apache/camel/component/rest/RestProducer.java  | 38 ++++++++++++++++++----
 .../rest/RestProducerUnresolvedPathWarnTest.java   | 32 +++++++++++++++++-
 2 files changed, 62 insertions(+), 8 deletions(-)

diff --git 
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
 
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
index f668f3de9fcf..8bc734d81506 100644
--- 
a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
+++ 
b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestProducer.java
@@ -23,7 +23,6 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Set;
 import java.util.StringJoiner;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -58,8 +57,14 @@ public class RestProducer extends DefaultAsyncProducer {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(RestProducer.class);
 
-    /** The path parameters already warned about, so a misconfigured route 
says it once and not per message. */
-    private final Set<String> warnedParameters = ConcurrentHashMap.newKeySet();
+    /**
+     * When each path parameter was last warned about: a misconfigured route 
says it once a minute, not per message, and
+     * not only once, as a storm of failures that follows would push a single 
warning out of sight (CAMEL-25373).
+     */
+    private final Map<String, Long> warnedParameters = new 
ConcurrentHashMap<>();
+
+    /** How often the warning about one path parameter is repeated while it 
stays unresolved; visible for tests. */
+    long warnIntervalMillis = 60_000;
 
     private final CamelContext camelContext;
     private final RestConfiguration configuration;
@@ -180,11 +185,17 @@ public class RestProducer extends DefaultAsyncProducer {
                 // the request is sent with the placeholder still in the path, 
and the service answers 404 for a
                 // path that holds a {name}, so say which parameter had no 
value (CAMEL-24986)
                 String unresolved = firstPlaceholder(resolvedUriTemplate);
-                if (unresolved != null && warnedParameters.add(unresolved)) {
+                if (unresolved != null && shouldWarn(unresolved)) {
+                    // a value kept as an exchange property is the usual 
mistake: the path is filled from headers and
+                    // variables only
+                    String property = exchange.getProperty(unresolved) != null
+                            ? " There is an exchange property " + unresolved + 
", but a path parameter is read from a"
+                              + " header or a variable, not from a property: 
use setHeader."
+                            : "";
                     LOG.warn("The path parameter {{}} of {} has no value: set 
the header {}, or an exchange variable"
-                             + " of that name, before the call. The request is 
sent with {{}} in the path, which the"
-                             + " service is unlikely to answer. This is logged 
once per parameter.",
-                            unresolved, resolvedUriTemplate, unresolved, 
unresolved);
+                             + " of that name, before the call.{} The request 
is sent with {{}} in the path, which the"
+                             + " service is unlikely to answer. This is logged 
at most once a minute per parameter.",
+                            unresolved, resolvedUriTemplate, unresolved, 
property, unresolved);
                 }
             }
         }
@@ -240,6 +251,19 @@ public class RestProducer extends DefaultAsyncProducer {
         }
     }
 
+    /** Whether to warn about the parameter now: the first time, and again 
once the interval has passed. */
+    private boolean shouldWarn(String parameter) {
+        long now = System.currentTimeMillis();
+        Long last = warnedParameters.get(parameter);
+        if (last != null && now - last < warnIntervalMillis) {
+            return false;
+        }
+        // two threads may both pass the check above; only the one that 
updates the entry warns
+        return last == null
+                ? warnedParameters.putIfAbsent(parameter, now) == null
+                : warnedParameters.replace(parameter, last, now);
+    }
+
     /**
      * The name of the first {@code {name}} left in the template, or null when 
every one of them was resolved. Only a
      * name counts, so a uri that holds braces for another reason is left 
alone (CAMEL-24986).
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/rest/RestProducerUnresolvedPathWarnTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/rest/RestProducerUnresolvedPathWarnTest.java
index 4811f470810e..58eb91989745 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/component/rest/RestProducerUnresolvedPathWarnTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/rest/RestProducerUnresolvedPathWarnTest.java
@@ -35,7 +35,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * A path parameter with no value leaves its {name} in the uri and the service 
answers 404 for it, so the producer says
- * which parameter it was. The request is still sent, as it was before 
(CAMEL-24986).
+ * which parameter it was. The request is still sent, as it was before 
(CAMEL-24986). The warning is repeated once a
+ * minute, and names an exchange property of the same name (CAMEL-25373).
  */
 public class RestProducerUnresolvedPathWarnTest {
 
@@ -126,4 +127,33 @@ public class RestProducerUnresolvedPathWarnTest {
         assertEquals("http://localhost/warnnone/1";, 
exchange.getIn().getHeader(Exchange.REST_HTTP_URI));
         assertTrue(warningsFor("warnnone").isEmpty(), warnings.toString());
     }
+
+    /** CAMEL-25373: the value kept as an exchange property is named, as that 
is the usual mistake. */
+    @Test
+    public void testSaysWhenTheValueIsAnExchangeProperty() throws Exception {
+        RestProducer producer = createProducer("rest:get:warnprop/{sku}");
+        Exchange exchange = producer.createExchange();
+        exchange.setProperty("sku", "CAMEL-MUG");
+
+        producer.process(exchange);
+
+        List<String> mine = warningsFor("warnprop");
+        assertEquals(1, mine.size(), warnings.toString());
+        assertTrue(mine.get(0).contains("There is an exchange property sku"), 
mine.get(0));
+        assertTrue(mine.get(0).contains("use setHeader"), mine.get(0));
+    }
+
+    /** CAMEL-25373: the warning comes back once the interval has passed, so a 
storm of failures does not bury it. */
+    @Test
+    public void testSaysItAgainAfterTheInterval() throws Exception {
+        RestProducer producer = createProducer("rest:get:warnagain/{id}");
+        producer.warnIntervalMillis = 0;
+
+        for (int i = 0; i < 3; i++) {
+            Exchange exchange = producer.createExchange();
+            producer.process(exchange);
+        }
+
+        assertEquals(3, warningsFor("warnagain").size(), warnings.toString());
+    }
 }

Reply via email to