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 20bbc3c8d8eb CAMEL-25101: camel-main - The "Property not 
auto-configured" warnings are never logged (#27004)
20bbc3c8d8eb is described below

commit 20bbc3c8d8ebb6e71cca95163de9ef4cf5ff314f
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Sep 28 23:20:49 2026 +0200

    CAMEL-25101: camel-main - The "Property not auto-configured" warnings are 
never logged (#27004)
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../org/apache/camel/main/BaseMainSupport.java     | 239 +++++++++------------
 .../main/MainNotAutoConfiguredWarningTest.java     | 114 ++++++++++
 .../apache/camel/util/BaseOrderedProperties.java   | 186 ++++++++++++++++
 .../apache/camel/util/OrderedPropertiesTest.java   |  45 ++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |  12 ++
 5 files changed, 455 insertions(+), 141 deletions(-)

diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index a213084e7f8b..9af1ceb78a3e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -941,8 +941,8 @@ public abstract class BaseMainSupport extends BaseService {
         // log which options was not set
         if (!properties.isEmpty()) {
             properties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.startupcondition.{}={} on object: {}", k, v,
-                        mainConfigurationProperties.startupCondition());
+                LOG.warn("Property not auto-configured: 
camel.startupcondition.{}={} on object: {}", k,
+                        maskValue(camelContext, k, v), 
mainConfigurationProperties.startupCondition());
             });
         }
 
@@ -1366,11 +1366,7 @@ public abstract class BaseMainSupport extends 
BaseService {
             setVaultProperties(camelContext, vaultProperties, 
mainConfigurationProperties.isAutoConfigurationFailFast(),
                     autoConfiguredProperties);
         }
-        if (!vaultProperties.isEmpty()) {
-            vaultProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.vault.{}={}", k, 
v);
-            });
-        }
+        warnNotAutoConfigured(camelContext, "camel.vault.", vaultProperties);
     }
 
     protected void doInitFileConfigurations(CamelContext camelContext, 
MainConfigurationProperties config) throws Exception {
@@ -1662,6 +1658,8 @@ public abstract class BaseMainSupport extends BaseService 
{
         if (!variableProperties.isEmpty()) {
             LOG.debug("Auto-configuring Variables from loaded properties: {}", 
variableProperties.size());
             MainSupportModelConfigurer.setVariableProperties(camelContext, 
variableProperties, autoConfiguredProperties);
+            // the variables have been set
+            variableProperties.clear();
         }
         // create beans first as they may be used later
         if (!beansProperties.isEmpty()) {
@@ -1733,22 +1731,26 @@ public abstract class BaseMainSupport extends 
BaseService {
                     mainConfigurationProperties.isAutoConfigurationFailFast(),
                     autoConfiguredProperties);
         }
+        // only one tracing service is used (the first that is enabled)
+        boolean tracing = false;
         if (!otelProperties.isEmpty() || 
mainConfigurationProperties.hasOtelConfiguration()) {
             LOG.debug("Auto-configuring OpenTelemetry from loaded properties: 
{}", otelProperties.size());
-            setOtelProperties(camelContext, otelProperties, 
mainConfigurationProperties.isAutoConfigurationFailFast(),
+            tracing = setOtelProperties(camelContext, otelProperties,
+                    mainConfigurationProperties.isAutoConfigurationFailFast(),
                     autoConfiguredProperties);
-        } else if (!otel2Properties.isEmpty() || 
mainConfigurationProperties.hasOtel2Configuration()) {
+        }
+        if (!tracing && (!otel2Properties.isEmpty() || 
mainConfigurationProperties.hasOtel2Configuration())) {
             LOG.debug("Auto-configuring OpenTelemetry 2 from loaded 
properties: {}", otel2Properties.size());
-            setOtel2Properties(camelContext, otel2Properties, 
mainConfigurationProperties.isAutoConfigurationFailFast(),
+            tracing = setOtel2Properties(camelContext, otel2Properties,
+                    mainConfigurationProperties.isAutoConfigurationFailFast(),
+                    autoConfiguredProperties);
+        }
+        // Attempt to fallback to Telemetry simple only if no other tracing 
service is found
+        if (!tracing && (!telemetryDevProperties.isEmpty() || 
mainConfigurationProperties.hasTelemetryDevConfiguration())) {
+            LOG.debug("Auto-configuring TelemetryDev from loaded properties: 
{}", telemetryDevProperties.size());
+            setTelemetryDevProperties(camelContext, telemetryDevProperties,
+                    mainConfigurationProperties.isAutoConfigurationFailFast(),
                     autoConfiguredProperties);
-        } else {
-            // Attempt to fallback to Telemetry simple only if no other 
tracing service is found
-            if (!telemetryDevProperties.isEmpty() || 
mainConfigurationProperties.hasTelemetryDevConfiguration()) {
-                LOG.debug("Auto-configuring TelemetryDev from loaded 
properties: {}", telemetryDevProperties.size());
-                setTelemetryDevProperties(camelContext, telemetryDevProperties,
-                        
mainConfigurationProperties.isAutoConfigurationFailFast(),
-                        autoConfiguredProperties);
-            }
         }
         if (!metricsProperties.isEmpty() || 
mainConfigurationProperties.hasMetricsConfiguration()) {
             LOG.debug("Auto-configuring Micrometer metrics from loaded 
properties: {}", metricsProperties.size());
@@ -1808,119 +1810,31 @@ public abstract class BaseMainSupport extends 
BaseService {
                 autoConfiguredProperties, resilience4jProperties, 
faultToleranceProperties);
 
         // log which options was not set
-        if (!variableProperties.isEmpty()) {
-            variableProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.variable.{}={}", 
k, v);
-            });
-        }
-        if (!beansProperties.isEmpty()) {
-            beansProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.beans.{}={}", k, 
v);
-            });
-        }
-        if (!contextProperties.isEmpty()) {
-            contextProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.context.{}={}", 
k, v);
-            });
-        }
-        if (!resilience4jProperties.isEmpty()) {
-            resilience4jProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.resilience4j.{}={}", k, v);
-            });
-        }
-        if (!faultToleranceProperties.isEmpty()) {
-            faultToleranceProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.faulttolerance.{}={}", k, v);
-            });
-        }
-        if (!restProperties.isEmpty()) {
-            restProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.rest.{}={}", k, 
v);
-            });
-        }
-        if (!threadPoolProperties.isEmpty()) {
-            threadPoolProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.threadpool.{}={}", k, v);
-            });
-        }
-        if (!healthProperties.isEmpty()) {
-            healthProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.health.{}={}", 
k, v);
-            });
-        }
-        if (!securityProperties.isEmpty()) {
-            securityProperties.forEach((k, v) -> LOG.warn("Property not 
auto-configured: camel.security.{}={}", k, v));
-        }
-        if (!sslProperties.isEmpty()) {
-            sslProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.ssl.{}={}", k, 
v);
-            });
-        }
-        if (!debuggerProperties.isEmpty()) {
-            debuggerProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.debug.{}={}", k, 
v);
-            });
-        }
-        if (!routeControllerProperties.isEmpty()) {
-            routeControllerProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.routeController.{}={}", k, v);
-            });
-        }
-        if (!errorRegistryProperties.isEmpty()) {
-            errorRegistryProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.errorRegistry.{}={}", k, v);
-            });
-        }
-        if (!aiObservabilityProperties.isEmpty()) {
-            aiObservabilityProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.aiObservability.{}={}", k, v);
-            });
-        }
-        if (!devConsoleProperties.isEmpty()) {
-            devConsoleProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.devConsole.{}={}", k, v);
-            });
-        }
-        if (!routeTemplateProperties.isEmpty()) {
-            routeTemplateProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.routetemplate.{}={}", k, v);
-            });
-        }
-        if (!lraProperties.isEmpty()) {
-            lraProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.lra.{}={}", k, 
v);
-            });
-        }
-        if (!otelProperties.isEmpty()) {
-            otelProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.opentelemetry.{}={}", k, v);
-            });
-        }
-        if (!otel2Properties.isEmpty()) {
-            otel2Properties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.opentelemetry2.{}={}", k, v);
-            });
-        }
-        if (!telemetryDevProperties.isEmpty()) {
-            telemetryDevProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.telemetryDev.{}={}", k, v);
-            });
-        }
-        if (!httpServerProperties.isEmpty()) {
-            httpServerProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.server.{}={}", 
k, v);
-            });
-        }
-        if (!httpManagementServerProperties.isEmpty()) {
-            httpManagementServerProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.management.{}={}", k, v);
-            });
-        }
-        if (!mdcProperties.isEmpty()) {
-            mdcProperties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.mdc.{}={}", k, 
v);
-            });
-        }
+        warnNotAutoConfigured(camelContext, "camel.variable.", 
variableProperties);
+        warnNotAutoConfigured(camelContext, "camel.beans.", beansProperties);
+        warnNotAutoConfigured(camelContext, "camel.context.", 
contextProperties);
+        warnNotAutoConfigured(camelContext, "camel.resilience4j.", 
resilience4jProperties);
+        warnNotAutoConfigured(camelContext, "camel.faulttolerance.", 
faultToleranceProperties);
+        warnNotAutoConfigured(camelContext, "camel.rest.", restProperties);
+        warnNotAutoConfigured(camelContext, "camel.threadpool.", 
threadPoolProperties);
+        warnNotAutoConfigured(camelContext, "camel.health.", healthProperties);
+        warnNotAutoConfigured(camelContext, "camel.security.", 
securityProperties);
+        warnNotAutoConfigured(camelContext, "camel.ssl.", sslProperties);
+        warnNotAutoConfigured(camelContext, "camel.debug.", 
debuggerProperties);
+        warnNotAutoConfigured(camelContext, "camel.routeController.", 
routeControllerProperties);
+        warnNotAutoConfigured(camelContext, "camel.errorRegistry.", 
errorRegistryProperties);
+        warnNotAutoConfigured(camelContext, "camel.aiObservability.", 
aiObservabilityProperties);
+        warnNotAutoConfigured(camelContext, "camel.devConsole.", 
devConsoleProperties);
+        warnNotAutoConfigured(camelContext, "camel.routetemplate.", 
routeTemplateProperties);
+        warnNotAutoConfigured(camelContext, "camel.lra.", lraProperties);
+        warnNotAutoConfigured(camelContext, "camel.opentelemetry.", 
otelProperties);
+        warnNotAutoConfigured(camelContext, "camel.opentelemetry2.", 
otel2Properties);
+        warnNotAutoConfigured(camelContext, "camel.telemetryDev.", 
telemetryDevProperties);
+        warnNotAutoConfigured(camelContext, "camel.server.", 
httpServerProperties);
+        warnNotAutoConfigured(camelContext, "camel.management.", 
httpManagementServerProperties);
+        warnNotAutoConfigured(camelContext, "camel.mdc.", mdcProperties);
+        warnNotAutoConfigured(camelContext, "camel.metrics.", 
metricsProperties);
+        warnNotAutoConfigured(camelContext, "camel.trace.", tracerProperties);
 
         // and call after all properties are set
         DefaultConfigurationConfigurer.afterPropertiesSet(camelContext);
@@ -2058,6 +1972,17 @@ public abstract class BaseMainSupport extends 
BaseService {
         }
     }
 
+    private static void warnNotAutoConfigured(
+            CamelContext camelContext, String prefix, 
OrderedLocationProperties properties) {
+        properties.forEach(
+                (k, v) -> LOG.warn("Property not auto-configured: {}{}={}", 
prefix, k, maskValue(camelContext, k, v)));
+    }
+
+    private static Object maskValue(CamelContext camelContext, Object key, 
Object value) {
+        // the values of sensitive options are masked
+        return MainHelper.containsSensitive(camelContext, key.toString(), 
value) ? "xxxxxx" : value;
+    }
+
     /**
      * Adds the options configured using the Java API (the options that are 
not the default value), which are not
      * already configured as properties (properties take precedence).
@@ -2079,7 +2004,7 @@ public abstract class BaseMainSupport extends BaseService 
{
         }
     }
 
-    private void setLraCheckProperties(
+    private boolean setLraCheckProperties(
             CamelContext camelContext, OrderedLocationProperties lraProperties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2109,6 +2034,11 @@ public abstract class BaseMainSupport extends 
BaseService {
             // add as service so saga can be active
             camelContext.addService(css, true, true);
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            lraProperties.clear();
+        }
+        return enabled;
     }
 
     private void setClusterServiceProperties(
@@ -2156,7 +2086,7 @@ public abstract class BaseMainSupport extends BaseService 
{
                 camelContext, factoryKey, CamelClusterService.class, "camel-" 
+ type);
     }
 
-    private void setOtelProperties(
+    private boolean setOtelProperties(
             CamelContext camelContext, OrderedLocationProperties 
otelProperties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2189,9 +2119,14 @@ public abstract class BaseMainSupport extends 
BaseService {
                 camelContext.addService(otel, true, true);
             }
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            otelProperties.clear();
+        }
+        return enabled;
     }
 
-    private void setOtel2Properties(
+    private boolean setOtel2Properties(
             CamelContext camelContext, OrderedLocationProperties 
otel2Properties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2211,9 +2146,14 @@ public abstract class BaseMainSupport extends 
BaseService {
                 camelContext.addService(otel, true, true);
             }
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            otel2Properties.clear();
+        }
+        return enabled;
     }
 
-    private void setMdcProperties(
+    private boolean setMdcProperties(
             CamelContext camelContext, OrderedLocationProperties mdcProperties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2233,9 +2173,14 @@ public abstract class BaseMainSupport extends 
BaseService {
                 camelContext.addService(mdc, true, true);
             }
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            mdcProperties.clear();
+        }
+        return enabled;
     }
 
-    private void setTelemetryDevProperties(
+    private boolean setTelemetryDevProperties(
             CamelContext camelContext, OrderedLocationProperties 
telemetryDevProperties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2256,9 +2201,14 @@ public abstract class BaseMainSupport extends 
BaseService {
                 camelContext.addService(telemetryDev, true, true);
             }
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            telemetryDevProperties.clear();
+        }
+        return enabled;
     }
 
-    private void setMetricsProperties(
+    private boolean setMetricsProperties(
             CamelContext camelContext, OrderedLocationProperties 
metricsProperties,
             boolean failIfNotSet, OrderedLocationProperties 
autoConfiguredProperties)
             throws Exception {
@@ -2291,6 +2241,11 @@ public abstract class BaseMainSupport extends 
BaseService {
                 camelContext.addService(micrometer, true, true);
             }
         }
+        if (!enabled) {
+            // the service is disabled so its options are not used
+            metricsProperties.clear();
+        }
+        return enabled;
     }
 
     private void setDevConsoleProperties(
@@ -2981,8 +2936,8 @@ public abstract class BaseMainSupport extends BaseService 
{
         // log which options was not set
         if (!properties.isEmpty()) {
             properties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: 
camel.component.properties.{}={} on object: {}", k, v,
-                        camelContext.getPropertiesComponent());
+                LOG.warn("Property not auto-configured: 
camel.component.properties.{}={} on object: {}", k,
+                        maskValue(camelContext, k, v), 
camelContext.getPropertiesComponent());
             });
         }
     }
@@ -3043,7 +2998,8 @@ public abstract class BaseMainSupport extends BaseService 
{
         // log which options was not set
         if (!properties.isEmpty()) {
             properties.forEach((k, v) -> {
-                LOG.warn("Property not auto-configured: camel.main.{}={} on 
bean: {}", k, v, config);
+                LOG.warn("Property not auto-configured: camel.main.{}={} on 
bean: {}", k, maskValue(camelContext, k, v),
+                        config);
             });
         }
     }
@@ -3214,7 +3170,8 @@ public abstract class BaseMainSupport extends BaseService 
{
                 PropertyOptionKey pok = entry.getKey();
                 OrderedLocationProperties values = entry.getValue();
                 values.forEach((k, v) -> {
-                    String stringValue = v != null ? v.toString() : null;
+                    Object value = maskValue(camelContext, k, v);
+                    String stringValue = value != null ? value.toString() : 
null;
                     LOG.warn("Property ({}={}) not auto-configured with name: 
{} on bean: {} with value: {}",
                             pok.getOptionPrefix() + "." + k, stringValue, k, 
pok.getInstance(), stringValue);
                 });
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainNotAutoConfiguredWarningTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainNotAutoConfiguredWarningTest.java
new file mode 100644
index 000000000000..8331a2d143ea
--- /dev/null
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainNotAutoConfiguredWarningTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.main;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.config.Property;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class MainNotAutoConfiguredWarningTest {
+
+    private static final String LOGGER = BaseMainSupport.class.getName();
+
+    private final List<String> warnings = new CopyOnWriteArrayList<>();
+    private AbstractAppender appender;
+
+    @BeforeEach
+    public void addAppender() {
+        appender = new AbstractAppender("MainNotAutoConfiguredWarningTest", 
null, null, true, Property.EMPTY_ARRAY) {
+            @Override
+            public void append(LogEvent event) {
+                if (event.getLevel() == Level.WARN) {
+                    warnings.add(event.getMessage().getFormattedMessage());
+                }
+            }
+        };
+        appender.start();
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        LoggerConfig loggerConfig = new LoggerConfig(LOGGER, Level.WARN, true);
+        loggerConfig.addAppender(appender, Level.WARN, null);
+        config.addLogger(LOGGER, loggerConfig);
+        ctx.updateLoggers();
+    }
+
+    @AfterEach
+    public void removeAppender() {
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        ctx.getConfiguration().removeLogger(LOGGER);
+        ctx.updateLoggers();
+        appender.stop();
+    }
+
+    private List<String> notAutoConfigured() {
+        return warnings.stream().filter(w -> w.contains("not 
auto-configured")).toList();
+    }
+
+    @Test
+    public void testTypoIsLogged() {
+        Main main = new Main();
+        main.configure().withAutoConfigurationFailFast(false);
+        main.addProperty("camel.rest.contxtPath", "/api");
+        main.addProperty("camel.rest.password", "S3cr3t");
+        main.start();
+        try {
+            List<String> list = notAutoConfigured();
+            assertEquals(2, list.size(), list.toString());
+            assertTrue(list.stream().anyMatch(w -> 
w.contains("camel.rest.contxtPath=/api")), list.toString());
+            // the value of a sensitive option is masked
+            assertTrue(list.stream().anyMatch(w -> 
w.contains("camel.rest.password=xxxxxx")), list.toString());
+            assertTrue(list.stream().noneMatch(w -> w.contains("S3cr3t")), 
list.toString());
+        } finally {
+            main.stop();
+        }
+    }
+
+    @Test
+    public void testNoWarningsForValidConfiguration() {
+        Main main = new Main();
+        main.configure().withAutoConfigurationFailFast(false);
+        main.addProperty("camel.variable.greeting", "Hello");
+        main.addProperty("camel.variable.global.foo", "123");
+        main.addProperty("camel.rest.contextPath", "/api");
+        main.addProperty("camel.lra.enabled", "false");
+        main.addProperty("camel.lra.coordinatorUrl", "http://localhost:8080";);
+        main.addProperty("camel.opentelemetry.enabled", "false");
+        main.addProperty("camel.opentelemetry.instrumentationName", "camel");
+        main.start();
+        try {
+            List<String> list = notAutoConfigured();
+            assertTrue(list.isEmpty(), list.toString());
+            assertEquals("Hello", 
main.getCamelContext().getVariable("greeting"));
+        } finally {
+            main.stop();
+        }
+    }
+}
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 92dc44fc9e7d..f533ee212a9f 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
@@ -21,12 +21,17 @@ import java.util.Collection;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import java.util.Vector;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
 /**
  * Base class for ordered properties implementations.
@@ -187,6 +192,187 @@ abstract class BaseOrderedProperties extends Properties {
         return new ArrayList<>(map.values());
     }
 
+    @Override
+    public Enumeration<Object> elements() {
+        lock.lock();
+        try {
+            return new Vector<>(map.values()).elements();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public void forEach(BiConsumer<? super Object, ? super Object> action) {
+        List<Map.Entry<String, Object>> entries;
+        lock.lock();
+        try {
+            // iterate a copy so the action can change the properties
+            entries = new ArrayList<>(map.entrySet());
+        } finally {
+            lock.unlock();
+        }
+        for (Map.Entry<String, Object> entry : entries) {
+            action.accept(entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public Object getOrDefault(Object key, Object defaultValue) {
+        Object answer = get(key);
+        return answer != null ? answer : defaultValue;
+    }
+
+    @Override
+    public Object putIfAbsent(Object key, Object value) {
+        lock.lock();
+        try {
+            Object answer = get(key);
+            if (answer == null) {
+                put(key, value);
+            }
+            return answer;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public boolean remove(Object key, Object value) {
+        lock.lock();
+        try {
+            if (containsKey(key) && Objects.equals(get(key), value)) {
+                remove(key);
+                return true;
+            }
+            return false;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public Object replace(Object key, Object value) {
+        lock.lock();
+        try {
+            return containsKey(key) ? put(key, value) : null;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public boolean replace(Object key, Object oldValue, Object newValue) {
+        lock.lock();
+        try {
+            if (containsKey(key) && Objects.equals(get(key), oldValue)) {
+                put(key, newValue);
+                return true;
+            }
+            return false;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public void replaceAll(BiFunction<? super Object, ? super Object, ?> 
function) {
+        lock.lock();
+        try {
+            for (String key : new ArrayList<>(map.keySet())) {
+                put(key, function.apply(key, get(key)));
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public Object computeIfAbsent(Object key, Function<? super Object, ?> 
mappingFunction) {
+        lock.lock();
+        try {
+            Object answer = get(key);
+            if (answer == null) {
+                answer = mappingFunction.apply(key);
+                if (answer != null) {
+                    put(key, answer);
+                }
+            }
+            return answer;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public Object computeIfPresent(Object key, BiFunction<? super Object, ? 
super Object, ?> remappingFunction) {
+        lock.lock();
+        try {
+            Object old = get(key);
+            if (old == null) {
+                return null;
+            }
+            Object answer = remappingFunction.apply(key, old);
+            if (answer == null) {
+                remove(key);
+            } else {
+                put(key, answer);
+            }
+            return answer;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public Object compute(Object key, BiFunction<? super Object, ? super 
Object, ?> remappingFunction) {
+        lock.lock();
+        try {
+            Object answer = remappingFunction.apply(key, get(key));
+            if (answer == null) {
+                remove(key);
+            } else {
+                put(key, answer);
+            }
+            return answer;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public Object merge(Object key, Object value, BiFunction<? super Object, ? 
super Object, ?> remappingFunction) {
+        lock.lock();
+        try {
+            Object old = get(key);
+            Object answer = old == null ? value : remappingFunction.apply(old, 
value);
+            if (answer == null) {
+                remove(key);
+            } else {
+                put(key, answer);
+            }
+            return answer;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o instanceof BaseOrderedProperties other) {
+            return map.equals(other.map);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return map.hashCode();
+    }
+
     @Override
     public String toString() {
         lock.lock();
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 9299f7643c42..0e4afa8bbac3 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
@@ -16,13 +16,18 @@
  */
 package org.apache.camel.util;
 
+import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.List;
 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.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class OrderedPropertiesTest {
@@ -113,4 +118,44 @@ public class OrderedPropertiesTest {
         assertFalse(prop.containsKey("foo"));
     }
 
+    @Test
+    public void testMapMethods() {
+        OrderedLocationProperties prop = new OrderedLocationProperties();
+        prop.put("app.properties", "b", "1");
+        prop.put("app.properties", "a", "2");
+
+        // forEach iterates the properties (in order)
+        List<Object> keys = new ArrayList<>();
+        prop.forEach((k, v) -> keys.add(k));
+        assertEquals(List.of("b", "a"), keys);
+
+        assertEquals("1", prop.getOrDefault("b", "x"));
+        assertEquals("x", prop.getOrDefault("c", "x"));
+
+        assertEquals("1", prop.putIfAbsent("b", "3"));
+        assertNull(prop.putIfAbsent("c", "3"));
+        assertEquals("3", prop.get("c"));
+
+        assertEquals("33", prop.compute("c", (k, v) -> v + "3"));
+        assertEquals("4", prop.computeIfAbsent("d", k -> "4"));
+        assertEquals("44", prop.merge("d", "4", (a, b) -> a + "" + b));
+        assertEquals("2", prop.replace("a", "22"));
+        assertTrue(prop.replace("a", "22", "222"));
+        assertEquals("222", prop.get("a"));
+        assertTrue(prop.remove("d", "44"));
+        assertFalse(prop.containsKey("d"));
+
+        List<Object> values = new ArrayList<>();
+        Enumeration<Object> e = prop.elements();
+        while (e.hasMoreElements()) {
+            values.add(e.nextElement());
+        }
+        assertEquals(List.of("1", "222", "33"), values);
+
+        OrderedLocationProperties other = new OrderedLocationProperties();
+        other.put("b", "1");
+        assertNotEquals(prop, other);
+        assertEquals(prop, prop);
+    }
+
 }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 2fff5abd625c..4a9d13e2e3ea 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -3045,6 +3045,18 @@ The accessors changed accordingly:
 The fluent builder `ParamDefinition.required(Boolean)` is unchanged, and a 
`required(String)` overload
 was added for placeholders. Routes written in XML, YAML or the Java DSL do not 
need any change.
 
+=== camel-main - properties that are not auto-configured are logged
+
+When `camel.main.autoConfigurationFailFast=false`, camel-main now logs a WARN 
for each `camel.*` property that could
+not be applied (such as a typo in the name of an option), for example
+`Property not auto-configured: camel.rest.contxtPath=/api`. These warnings 
were never logged before. The values of
+sensitive options (such as passwords) are masked. With fail-fast (the default) 
an unknown property fails the startup
+as before.
+
+When `camel.opentelemetry.*` properties are configured but OpenTelemetry is 
disabled (`camel.opentelemetry.enabled=false`),
+the `camel.opentelemetry2.*` or `camel.telemetryDev.*` properties are now 
used. Previously they were ignored whenever
+any `camel.opentelemetry.*` property was configured.
+
 === camel-seda - stopping a suspended route does not wait for its pending 
messages
 
 Stopping a suspended SEDA route, or stopping the CamelContext while such a 
route is suspended, no longer waits for the

Reply via email to