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 4ca15b8754ca CAMEL-23971: fix ordered properties containsKey support
(#24541)
4ca15b8754ca is described below
commit 4ca15b8754caddefccccd27881d29699870bac27
Author: Adriano Machado <[email protected]>
AuthorDate: Thu Jul 9 04:53:00 2026 -0400
CAMEL-23971: fix ordered properties containsKey support (#24541)
* CAMEL-23971: fix ordered properties containsKey support
Delegate OrderedProperties containment checks to the backing map and add
regression coverage for containsKey, containsValue, legacy contains, and remove
behavior. Also switch ExportCamelMain profile presence checks to containsKey so
explicit keys are treated as set even when their value is empty.
Why: BaseOrderedProperties moved storage into a LinkedHashMap but never
overrode the Hashtable containment methods, which broke property presence
checks in Camel Main and Camel JBang/TUI code paths.
Co-authored-by: Codex <[email protected]>
* CAMEL-23971: override containsKey in CamelCaseOrderedProperties for
camelCase/dash fallback
Address review feedback on PR #24541. CamelCaseOrderedProperties overrides
get/getProperty to look up keys as-is, then dashToCamelCase, then
camelCaseToDash. The inherited BaseOrderedProperties.containsKey only
checked
the exact key, so containsKey was inconsistent with the get semantics and
ExportCamelMain's profile presence checks could miss dash-style keys such as
camel.management.metrics-enabled.
Override containsKey to apply the same fallback so it stays consistent with
get/getProperty. Only containsKey needs this; values are never transformed,
so
containsValue/contains remain the plain base-class delegation.
Reviewed all BaseOrderedProperties descendants: OrderedProperties (no read
overrides) and OrderedLocationProperties (only clear/remove overrides, no
key
transformation on read) need no containment changes.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
* CAMEL-23971: read backing map directly in
CamelCaseOrderedProperties.containsKey
Mirror the get()/getProperty() pattern where the inner lookup does not
re-acquire the lock, instead of calling super.containsKey() three times.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
---------
Co-authored-by: Codex <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
.../apache/camel/util/BaseOrderedProperties.java | 30 ++++++++++++++++
.../camel/util/CamelCaseOrderedProperties.java | 15 ++++++++
.../camel/util/CamelCaseOrderedPropertiesTest.java | 19 ++++++++++
.../apache/camel/util/OrderedPropertiesTest.java | 41 ++++++++++++++++++++++
.../dsl/jbang/core/commands/ExportCamelMain.java | 8 ++---
5 files changed, 109 insertions(+), 4 deletions(-)
diff --git
a/core/camel-util/src/main/java/org/apache/camel/util/BaseOrderedProperties.java
b/core/camel-util/src/main/java/org/apache/camel/util/BaseOrderedProperties.java
index ed2f79e89cef..92dc44fc9e7d 100644
---
a/core/camel-util/src/main/java/org/apache/camel/util/BaseOrderedProperties.java
+++
b/core/camel-util/src/main/java/org/apache/camel/util/BaseOrderedProperties.java
@@ -76,6 +76,36 @@ abstract class BaseOrderedProperties extends Properties {
}
}
+ @Override
+ public boolean containsKey(Object key) {
+ lock.lock();
+ try {
+ return map.containsKey(key);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ lock.lock();
+ try {
+ return map.containsValue(value);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public boolean contains(Object value) {
+ lock.lock();
+ try {
+ return map.containsValue(value);
+ } finally {
+ lock.unlock();
+ }
+ }
+
@Override
public boolean isEmpty() {
lock.lock();
diff --git
a/core/camel-util/src/main/java/org/apache/camel/util/CamelCaseOrderedProperties.java
b/core/camel-util/src/main/java/org/apache/camel/util/CamelCaseOrderedProperties.java
index 127f883d80b4..6b3602b249eb 100644
---
a/core/camel-util/src/main/java/org/apache/camel/util/CamelCaseOrderedProperties.java
+++
b/core/camel-util/src/main/java/org/apache/camel/util/CamelCaseOrderedProperties.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.util;
+import java.util.Map;
import java.util.Properties;
/**
@@ -43,6 +44,20 @@ public final class CamelCaseOrderedProperties extends
BaseOrderedProperties {
}
}
+ @Override
+ public boolean containsKey(Object key) {
+ lock.lock();
+ try {
+ String k = key.toString();
+ Map<String, Object> m = asMap();
+ return m.containsKey(k)
+ || m.containsKey(StringHelper.dashToCamelCase(k))
+ || m.containsKey(StringHelper.camelCaseToDash(k));
+ } finally {
+ lock.unlock();
+ }
+ }
+
@Override
public String getProperty(String key) {
String answer = super.getProperty(key);
diff --git
a/core/camel-util/src/test/java/org/apache/camel/util/CamelCaseOrderedPropertiesTest.java
b/core/camel-util/src/test/java/org/apache/camel/util/CamelCaseOrderedPropertiesTest.java
index bb5d31d8569a..54605d0cac65 100644
---
a/core/camel-util/src/test/java/org/apache/camel/util/CamelCaseOrderedPropertiesTest.java
+++
b/core/camel-util/src/test/java/org/apache/camel/util/CamelCaseOrderedPropertiesTest.java
@@ -22,6 +22,8 @@ import java.util.Properties;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class CamelCaseOrderedPropertiesTest {
@@ -77,4 +79,21 @@ public class CamelCaseOrderedPropertiesTest {
assertEquals("1234",
prop.getProperty("camel.component.direct.timeout", "MyDefault"));
}
+ @Test
+ public void testContainsKeyCamelCaseAndDashFallback() {
+ Properties prop = new CamelCaseOrderedProperties();
+ prop.setProperty("camel.main.stream-caching-enabled", "true");
+ prop.setProperty("camel.component.seda.queueSize", "500");
+
+ // stored as dash, looked up as dash or camelCase
+ assertTrue(prop.containsKey("camel.main.stream-caching-enabled"));
+ assertTrue(prop.containsKey("camel.main.streamCachingEnabled"));
+
+ // stored as camelCase, looked up as camelCase or dash
+ assertTrue(prop.containsKey("camel.component.seda.queueSize"));
+ assertTrue(prop.containsKey("camel.component.seda.queue-size"));
+
+ assertFalse(prop.containsKey("camel.main.unknown"));
+ }
+
}
diff --git
a/core/camel-util/src/test/java/org/apache/camel/util/OrderedPropertiesTest.java
b/core/camel-util/src/test/java/org/apache/camel/util/OrderedPropertiesTest.java
index 00c34d328703..9299f7643c42 100644
---
a/core/camel-util/src/test/java/org/apache/camel/util/OrderedPropertiesTest.java
+++
b/core/camel-util/src/test/java/org/apache/camel/util/OrderedPropertiesTest.java
@@ -22,6 +22,8 @@ import java.util.Properties;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class OrderedPropertiesTest {
@@ -72,4 +74,43 @@ public class OrderedPropertiesTest {
assertEquals("1234", it.next());
}
+ @Test
+ public void testContainsKey() {
+ Properties prop = new OrderedProperties();
+ prop.setProperty("foo", "bar");
+
+ assertTrue(prop.containsKey("foo"));
+ assertFalse(prop.containsKey("bar"));
+ }
+
+ @Test
+ public void testContainsValue() {
+ Properties prop = new OrderedProperties();
+ prop.setProperty("foo", "bar");
+
+ assertTrue(prop.containsValue("bar"));
+ assertFalse(prop.containsValue("foo"));
+ }
+
+ @Test
+ public void testContainsLegacy() {
+ Properties prop = new OrderedProperties();
+ prop.setProperty("foo", "bar");
+
+ assertTrue(prop.contains("bar"));
+ assertFalse(prop.contains("foo"));
+ }
+
+ @Test
+ public void testContainsKeyAfterRemove() {
+ Properties prop = new OrderedProperties();
+ prop.setProperty("foo", "bar");
+
+ assertTrue(prop.containsKey("foo"));
+
+ prop.remove("foo");
+
+ assertFalse(prop.containsKey("foo"));
+ }
+
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
index a5e1265aa2d9..4dcbc8b41f57 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
@@ -287,13 +287,13 @@ class ExportCamelMain extends Export {
Properties prop = new CamelCaseOrderedProperties();
RuntimeUtil.loadProperties(prop, profile);
// if metrics is defined then include camel-micrometer-prometheus
for camel-main runtime
- if (prop.getProperty("camel.metrics.enabled") != null
- || prop.getProperty("camel.management.metricsEnabled") !=
null
- || prop.getProperty("camel.server.metricsEnabled") !=
null) {
+ if (prop.containsKey("camel.metrics.enabled")
+ || prop.containsKey("camel.management.metricsEnabled")
+ || prop.containsKey("camel.server.metricsEnabled")) {
answer.add("mvn:org.apache.camel:camel-micrometer-prometheus");
}
// if health-check is defined then include camel-health for
camel-main runtime
- if (prop.getProperty("camel.management.healthCheckEnabled") !=
null) {
+ if (prop.containsKey("camel.management.healthCheckEnabled")) {
answer.add("mvn:org.apache.camel:camel-health");
}
}