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 e878f03b77d CAMEL-21353: camel-core - Add possibility to set some 
condition for Camel to wait during startup before continuing (#15999)
e878f03b77d is described below

commit e878f03b77d63b76181d45c299c50444f7f558eb
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Oct 17 19:04:49 2024 +0200

    CAMEL-21353: camel-core - Add possibility to set some condition for Camel 
to wait during startup before continuing (#15999)
---
 .../main/camel-main-configuration-metadata.json    |   8 +
 .../org/apache/camel/spi/StartupCondition.java     |  57 ++++++
 .../apache/camel/spi/StartupConditionStrategy.java |  89 ++++++++++
 .../camel/impl/engine/AbstractCamelContext.java    |   9 +
 .../engine/DefaultStartupConditionStrategy.java    | 187 ++++++++++++++++++++
 .../camel/impl/engine/SimpleCamelContext.java      |   6 +
 ...Test.java => StartupConditionRegistryTest.java} |  60 +++----
 ...extStartTest.java => StartupConditionTest.java} |  57 +++---
 .../camel/impl/VetoCamelContextStartTest.java      |   2 +-
 ...ConditionConfigurationPropertiesConfigurer.java | 101 +++++++++++
 .../camel-main-configuration-metadata.json         |   8 +
 ...el.main.StartupConditionConfigurationProperties |   2 +
 core/camel-main/src/main/docs/main.adoc            |  16 ++
 .../org/apache/camel/main/BaseMainSupport.java     |  95 ++++++++++
 .../camel/main/DefaultConfigurationConfigurer.java |   5 +
 .../camel/main/MainConfigurationProperties.java    |  11 ++
 .../StartupConditionConfigurationProperties.java   | 194 +++++++++++++++++++++
 .../camel/main/MainStartupConditionEnvTest.java    |  57 ++++++
 .../camel/main/MainStartupConditionTest.java       |  62 +++++++
 .../main/MainStartupConditionTimeoutTest.java      |  59 +++++++
 .../camel/support/startup/EnvStartupCondition.java |  61 +++++++
 .../support/startup/FileStartupCondition.java      |  61 +++++++
 docs/user-manual/modules/ROOT/nav.adoc             |   1 +
 docs/user-manual/modules/ROOT/pages/lifecycle.adoc |   6 +
 .../modules/ROOT/pages/startup-condition.adoc      |  40 +++++
 .../maven/packaging/PrepareCamelMainMojo.java      |   7 +-
 26 files changed, 1196 insertions(+), 65 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 934f069bb93..77580418ad4 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -1,6 +1,7 @@
 {
   "groups": [
     { "name": "camel.main", "description": "Camel Main configurations", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties" },
+    { "name": "camel.startupcondition", "description": "Camel Startup 
Condition configurations", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties" },
     { "name": "camel.routecontroller", "description": "Camel Route Controller 
configurations", "sourceType": 
"org.apache.camel.main.RouteControllerConfigurationProperties" },
     { "name": "camel.server", "description": "Camel Embedded HTTP Server (only 
for standalone; not Spring Boot or Quarkus) configurations", "sourceType": 
"org.apache.camel.main.HttpServerConfigurationProperties" },
     { "name": "camel.debug", "description": "Camel Debugger configurations", 
"sourceType": "org.apache.camel.main.DebuggerConfigurationProperties" },
@@ -303,6 +304,13 @@
     { "name": "camel.ssl.trustAllCertificates", "description": "Allows to 
trust all SSL certificates without performing certificate validation. This can 
be used in development environment but may expose the system to security risks. 
Notice that if the trustAllCertificates option is set to true then the 
trustStore\/trustStorePassword options are not in use..", "sourceType": 
"org.apache.camel.main.SSLConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.ssl.trustStore", "description": "The trust store to load. 
The trust store is by default loaded from classpath. If you must load from file 
system, then use file: as prefix. file:nameOfFile (to refer to the file system) 
classpath:nameOfFile (to refer to the classpath; default) http:uri (to load the 
resource using HTTP) ref:nameOfBean (to lookup an existing KeyStore instance 
from the registry, for example for testing and development).", "sourceType": 
"org.apache.camel.m [...]
     { "name": "camel.ssl.trustStorePassword", "description": "Sets the SSL 
Truststore password.", "sourceType": 
"org.apache.camel.main.SSLConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.customClassNames", "description": "A 
list of custom class names (FQN). Multiple classes can be separated by comma.", 
"sourceType": "org.apache.camel.main.StartupConditionConfigurationProperties", 
"type": "string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.enabled", "description": "To enable 
using startup conditions", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false },
+    { "name": "camel.startupcondition.environmentVariableExists", 
"description": "Wait for an environment variable with the given name to exists 
before continuing", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.failOnTimeout", "description": "Whether 
to fail if the check timed out. The default is to fail and throw an exception 
causing Camel to not be able to startup.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": true },
+    { "name": "camel.startupcondition.fileExists", "description": "Wait for a 
file with the given name to exists before continuing", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.interval", "description": "Interval in 
millis between checking conditions.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"integer", "javaType": "int", "defaultValue": 100 },
+    { "name": "camel.startupcondition.timeout", "description": "Total timeout 
(in millis) for all startup conditions.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"integer", "javaType": "int", "defaultValue": 10000 },
     { "name": "camel.threadpool.allowCoreThreadTimeOut", "description": "Sets 
default whether to allow core threads to timeout", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "boolean", 
"javaType": "java.lang.Boolean", "defaultValue": "false" },
     { "name": "camel.threadpool.config", "description": "Adds a configuration 
for a specific thread pool profile (inherits default values)", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "object", 
"javaType": "java.util.Map" },
     { "name": "camel.threadpool.keepAliveTime", "description": "Sets the 
default keep alive time for inactive threads", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "integer", 
"javaType": "java.lang.Long" },
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/StartupCondition.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/StartupCondition.java
new file mode 100644
index 00000000000..e0e18928969
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/StartupCondition.java
@@ -0,0 +1,57 @@
+/*
+ * 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.spi;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Pluggable condition that must be accepted before Camel can continue 
starting up.
+ *
+ * This can be used to let Camel wait for a specific file to be present, an 
environment-variable, or some other custom
+ * conditions.
+ */
+public interface StartupCondition {
+
+    /**
+     * The name of condition used for logging purposes.
+     */
+    default String getName() {
+        return this.getClass().getSimpleName();
+    }
+
+    /**
+     * Optional logging message to log before waiting for the condition
+     */
+    default String getWaitMessage() {
+        return null;
+    }
+
+    /**
+     * Optional logging message to log if condition was not meet.
+     */
+    default String getFailureMessage() {
+        return null;
+    }
+
+    /**
+     * Checks if the condition is accepted
+     *
+     * @param  camelContext the Camel context (is not fully initialized)
+     * @return              true to continue, false to stop and fail.
+     */
+    boolean canContinue(CamelContext camelContext) throws Exception;
+}
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/StartupConditionStrategy.java
 
b/core/camel-api/src/main/java/org/apache/camel/spi/StartupConditionStrategy.java
new file mode 100644
index 00000000000..0201522e1a6
--- /dev/null
+++ 
b/core/camel-api/src/main/java/org/apache/camel/spi/StartupConditionStrategy.java
@@ -0,0 +1,89 @@
+/*
+ * 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.spi;
+
+import java.util.List;
+
+import org.apache.camel.StaticService;
+
+/**
+ * Strategy for performing checks on startup that can validate whether Camel 
can be started, or wait for some conditions
+ * to be satisfied, before Camel can continue to startup.
+ *
+ * @see StartupCondition
+ */
+public interface StartupConditionStrategy extends StaticService {
+
+    /**
+     * To enable or disable startup checks
+     */
+    boolean isEnabled();
+
+    /**
+     * To enable or disable startup checks
+     */
+    void setEnabled(boolean enabled);
+
+    /**
+     * Interval in millis between checking startup conditions
+     */
+    void setInterval(int interval);
+
+    /**
+     * Interval in millis between checking startup conditions
+     */
+    int getInterval();
+
+    /**
+     * Total timeout in millis when performing startup checks.
+     */
+    void setTimeout(int timeout);
+
+    /**
+     * Total timeout in millis when performing startup checks.
+     */
+    int getTimeout();
+
+    /**
+     * Whether to fail if the check timed out. The default is to fail and 
throw an exception causing Camel to not be
+     * able to startup.
+     */
+    boolean isFailOnTimeout();
+
+    /**
+     * Whether to fail if the check timed out. The default is to fail and 
throw an exception causing Camel to not be
+     * able to startup.
+     */
+    void setFailOnTimeout(boolean failOnTimeout);
+
+    /**
+     * Adds a custom {@link StartupCondition} check to be performed.
+     */
+    void addStartupCondition(StartupCondition startupCondition);
+
+    /**
+     * Lists all the {@link StartupCondition}.
+     */
+    List<StartupCondition> getStartupConditions();
+
+    /**
+     * Checks all {@link StartupCondition} whether they are satisfied. If 
everything is okay, then this method returns,
+     * otherwise if a condition is failing then an exception is thrown.
+     */
+    void checkStartupConditions() throws Exception;
+
+}
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 4bca692a410..4a2a086f79a 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -160,6 +160,7 @@ import org.apache.camel.spi.RouteTemplateParameterSource;
 import org.apache.camel.spi.RoutesLoader;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.StartupConditionStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.Tracer;
@@ -340,6 +341,7 @@ public abstract class AbstractCamelContext extends 
BaseService
      * Called during object construction to initialize context plugins
      */
     protected void initPlugins() {
+        camelContextExtension.addContextPlugin(StartupConditionStrategy.class, 
createStartupConditionStrategy());
         camelContextExtension.addContextPlugin(CamelBeanPostProcessor.class, 
createBeanPostProcessor());
         
camelContextExtension.addContextPlugin(CamelDependencyInjectionAnnotationFactory.class,
                 createDependencyInjectionAnnotationFactory());
@@ -2360,6 +2362,11 @@ public abstract class AbstractCamelContext extends 
BaseService
         }
 
         addService(getManagementStrategy(), false);
+
+        // check startup conditions before we can continue
+        StartupConditionStrategy scs = 
getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
+        scs.checkStartupConditions();
+
         lifecycleStrategies.sort(OrderedComparator.get());
         ServiceHelper.initService(lifecycleStrategies);
         for (LifecycleStrategy strategy : lifecycleStrategies) {
@@ -4265,6 +4272,8 @@ public abstract class AbstractCamelContext extends 
BaseService
 
     protected abstract EndpointServiceRegistry createEndpointServiceRegistry();
 
+    protected abstract StartupConditionStrategy 
createStartupConditionStrategy();
+
     protected RestConfiguration createRestConfiguration() {
         // lookup a global which may have been on a container such spring-boot 
/ CDI / etc.
         RestConfiguration conf
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStartupConditionStrategy.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStartupConditionStrategy.java
new file mode 100644
index 00000000000..b3bd5a2bacf
--- /dev/null
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStartupConditionStrategy.java
@@ -0,0 +1,187 @@
+/*
+ * 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.impl.engine;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.VetoCamelContextStartException;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.spi.StartupConditionStrategy;
+import org.apache.camel.support.OrderedComparator;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.StopWatch;
+import org.apache.camel.util.TimeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Default {@link StartupConditionStrategy}.
+ */
+public class DefaultStartupConditionStrategy extends ServiceSupport implements 
StartupConditionStrategy, CamelContextAware {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(DefaultStartupConditionStrategy.class);
+
+    private CamelContext camelContext;
+    private final List<StartupCondition> conditions = new ArrayList<>();
+    private boolean enabled;
+    private int interval = 500;
+    private int timeout = 10000;
+    private boolean failOnTimeout = true;
+    private volatile boolean checkDone;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public int getInterval() {
+        return interval;
+    }
+
+    public void setInterval(int interval) {
+        this.interval = interval;
+    }
+
+    @Override
+    public int getTimeout() {
+        return timeout;
+    }
+
+    @Override
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    @Override
+    public boolean isFailOnTimeout() {
+        return failOnTimeout;
+    }
+
+    @Override
+    public void setFailOnTimeout(boolean failOnTimeout) {
+        this.failOnTimeout = failOnTimeout;
+    }
+
+    @Override
+    public void addStartupCondition(StartupCondition startupCondition) {
+        conditions.add(startupCondition);
+    }
+
+    @Override
+    public List<StartupCondition> getStartupConditions() {
+        return conditions;
+    }
+
+    @Override
+    public void checkStartupConditions() throws VetoCamelContextStartException 
{
+        if (!checkDone && enabled) {
+            try {
+                var list = new ArrayList<>(conditions);
+                
list.addAll(camelContext.getRegistry().findByType(StartupCondition.class));
+                list.sort(OrderedComparator.get());
+                doCheckConditions(list);
+            } finally {
+                checkDone = true;
+            }
+        }
+    }
+
+    protected void doCheckConditions(List<StartupCondition> conditions) throws 
VetoCamelContextStartException {
+        StopWatch watch = new StopWatch();
+        boolean first = true;
+        int tick = 1;
+        int counter = 1;
+        while (watch.taken() < timeout) {
+            boolean ok = true;
+            for (StartupCondition startup : conditions) {
+                if (first) {
+                    String msg = startup.getWaitMessage();
+                    if (msg != null) {
+                        LOG.info(msg);
+                    }
+                }
+                if (ok) {
+                    try {
+                        LOG.trace("canContinue attempt #{}: {}", counter, 
startup.getName());
+                        ok = startup.canContinue(camelContext);
+                        LOG.debug("canContinue attempt #{}: {} -> {}", 
counter, startup.getName(), ok);
+                    } catch (Exception e) {
+                        throw new VetoCamelContextStartException(
+                                "Startup condition " + startup.getName() + " 
failed due to: " + e.getMessage(), e,
+                                camelContext);
+                    }
+                }
+            }
+            if (ok) {
+                return;
+            }
+
+            first = false;
+            // wait a bit before next loop
+            try {
+                Thread.sleep(interval);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                return;
+            }
+            // log waiting but only once per second
+            long seconds = watch.taken() / 1000;
+            if (seconds > tick) {
+                // tick counter
+                tick++;
+                // log if taking some unexpected time
+                if (tick % 2 == 0) {
+                    LOG.info("Waited {} for startup conditions to 
continue...", TimeUtils.printDuration(watch.taken()));
+                }
+            }
+            counter++;
+        }
+
+        String error = "Startup condition timeout error";
+        for (StartupCondition startup : conditions) {
+            String msg = startup.getFailureMessage();
+            if (msg != null) {
+                error = "Startup condition: " + startup.getName() + " cannot 
continue due to: " + msg;
+            }
+        }
+        if (isFailOnTimeout()) {
+            throw new VetoCamelContextStartException(error, camelContext);
+        } else {
+            LOG.warn(error);
+        }
+    }
+
+}
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index a91093d3b3c..266f416e8e0 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -85,6 +85,7 @@ import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RouteFactory;
 import org.apache.camel.spi.RoutesLoader;
 import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.StartupConditionStrategy;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.Tracer;
 import org.apache.camel.spi.TransformerRegistry;
@@ -732,6 +733,11 @@ public class SimpleCamelContext extends 
AbstractCamelContext {
         return new DefaultEndpointServiceRegistry(getCamelContextReference());
     }
 
+    @Override
+    protected StartupConditionStrategy createStartupConditionStrategy() {
+        return new DefaultStartupConditionStrategy();
+    }
+
     @Override
     protected TransformerRegistry createTransformerRegistry() {
         return new DefaultTransformerRegistry(getCamelContextReference());
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionRegistryTest.java
similarity index 50%
copy from 
core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
copy to 
core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionRegistryTest.java
index 091617d406a..e91c914d924 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionRegistryTest.java
@@ -18,56 +18,54 @@ package org.apache.camel.impl;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
-import org.apache.camel.VetoCamelContextStartException;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.LifecycleStrategy;
-import org.apache.camel.support.LifecycleStrategySupport;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.spi.StartupConditionStrategy;
 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;
+import static org.junit.jupiter.api.Assertions.fail;
 
-/**
- *
- */
-public class VetoCamelContextStartTest extends ContextTestSupport {
+public class StartupConditionRegistryTest extends ContextTestSupport {
 
-    private final LifecycleStrategy veto = new MyVeto();
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
 
     @Test
     public void testVetoCamelContextStart() {
-        // context is veto'ed but appears as started
-        assertFalse(context.getStatus().isStarted());
-        assertTrue(context.getStatus().isStopped());
-        assertEquals(0, context.getRoutes().size());
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-        return new RouteBuilder() {
-            @Override
-            public void configure() {
-                from("direct:start").to("mock:result");
-            }
-        };
+        try {
+            context.start();
+            fail("Should throw exception");
+        } catch (Exception e) {
+            assertEquals("Startup condition: MyOtherCondition cannot continue 
due to: forced error from unit test",
+                    e.getCause().getMessage());
+        }
     }
 
     @Override
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
-        context.addLifecycleStrategy(veto);
+
+        StartupConditionStrategy scs = 
context.getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
+        scs.setEnabled(true);
+        scs.setTimeout(250);
+
+        context.getRegistry().bind("myCondition", new MyOtherCondition());
+
         return context;
     }
 
-    private static class MyVeto extends LifecycleStrategySupport {
+    private static class MyOtherCondition implements StartupCondition {
 
         @Override
-        public void onContextStarting(CamelContext context) throws 
VetoCamelContextStartException {
-            // we just want camel context to not startup, but do not rethrow
-            // exception
-            throw new VetoCamelContextStartException("Forced", context, false);
+        public String getFailureMessage() {
+            return "forced error from unit test";
         }
 
+        @Override
+        public boolean canContinue(CamelContext camelContext) throws Exception 
{
+            return false;
+        }
     }
 }
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
 b/core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionTest.java
similarity index 50%
copy from 
core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
copy to 
core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionTest.java
index 091617d406a..4a713774a96 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/StartupConditionTest.java
@@ -18,56 +18,51 @@ package org.apache.camel.impl;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
-import org.apache.camel.VetoCamelContextStartException;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.LifecycleStrategy;
-import org.apache.camel.support.LifecycleStrategySupport;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.spi.StartupConditionStrategy;
 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;
+import static org.junit.jupiter.api.Assertions.fail;
 
-/**
- *
- */
-public class VetoCamelContextStartTest extends ContextTestSupport {
+public class StartupConditionTest extends ContextTestSupport {
 
-    private final LifecycleStrategy veto = new MyVeto();
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
 
     @Test
     public void testVetoCamelContextStart() {
-        // context is veto'ed but appears as started
-        assertFalse(context.getStatus().isStarted());
-        assertTrue(context.getStatus().isStopped());
-        assertEquals(0, context.getRoutes().size());
-    }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() {
-        return new RouteBuilder() {
-            @Override
-            public void configure() {
-                from("direct:start").to("mock:result");
-            }
-        };
+        try {
+            context.start();
+            fail("Should throw exception");
+        } catch (Exception e) {
+            assertEquals("Startup condition: MyCondition cannot continue due 
to: forced error from unit test",
+                    e.getCause().getMessage());
+        }
     }
 
     @Override
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
-        context.addLifecycleStrategy(veto);
+        StartupConditionStrategy scs = 
context.getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
+        scs.setEnabled(true);
+        scs.setTimeout(250);
+        scs.addStartupCondition(new MyCondition());
         return context;
     }
 
-    private static class MyVeto extends LifecycleStrategySupport {
+    private static class MyCondition implements StartupCondition {
 
         @Override
-        public void onContextStarting(CamelContext context) throws 
VetoCamelContextStartException {
-            // we just want camel context to not startup, but do not rethrow
-            // exception
-            throw new VetoCamelContextStartException("Forced", context, false);
+        public String getFailureMessage() {
+            return "forced error from unit test";
         }
 
+        @Override
+        public boolean canContinue(CamelContext camelContext) throws Exception 
{
+            return false;
+        }
     }
 }
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
index 091617d406a..ae765b1ecd8 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/VetoCamelContextStartTest.java
@@ -37,7 +37,7 @@ public class VetoCamelContextStartTest extends 
ContextTestSupport {
 
     @Test
     public void testVetoCamelContextStart() {
-        // context is veto'ed but appears as started
+        // context is veto'ed and appears as stopped
         assertFalse(context.getStatus().isStarted());
         assertTrue(context.getStatus().isStopped());
         assertEquals(0, context.getRoutes().size());
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/StartupConditionConfigurationPropertiesConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/StartupConditionConfigurationPropertiesConfigurer.java
new file mode 100644
index 00000000000..ef23844bbf6
--- /dev/null
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/StartupConditionConfigurationPropertiesConfigurer.java
@@ -0,0 +1,101 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.main;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.main.StartupConditionConfigurationProperties;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateConfigurerMojo")
+@SuppressWarnings("unchecked")
+public class StartupConditionConfigurationPropertiesConfigurer extends 
org.apache.camel.support.component.PropertyConfigurerSupport implements 
GeneratedPropertyConfigurer, ExtendedPropertyConfigurerGetter {
+
+    private static final Map<String, Object> ALL_OPTIONS;
+    static {
+        Map<String, Object> map = new CaseInsensitiveMap();
+        map.put("CustomClassNames", java.lang.String.class);
+        map.put("Enabled", boolean.class);
+        map.put("EnvironmentVariableExists", java.lang.String.class);
+        map.put("FailOnTimeout", boolean.class);
+        map.put("FileExists", java.lang.String.class);
+        map.put("Interval", int.class);
+        map.put("Timeout", int.class);
+        ALL_OPTIONS = map;
+        
ConfigurerStrategy.addBootstrapConfigurerClearer(StartupConditionConfigurationPropertiesConfigurer::clearBootstrapConfigurers);
+    }
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        org.apache.camel.main.StartupConditionConfigurationProperties target = 
(org.apache.camel.main.StartupConditionConfigurationProperties) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "customclassnames":
+        case "customClassNames": 
target.setCustomClassNames(property(camelContext, java.lang.String.class, 
value)); return true;
+        case "enabled": target.setEnabled(property(camelContext, 
boolean.class, value)); return true;
+        case "environmentvariableexists":
+        case "environmentVariableExists": 
target.setEnvironmentVariableExists(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "failontimeout":
+        case "failOnTimeout": target.setFailOnTimeout(property(camelContext, 
boolean.class, value)); return true;
+        case "fileexists":
+        case "fileExists": target.setFileExists(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "interval": target.setInterval(property(camelContext, int.class, 
value)); return true;
+        case "timeout": target.setTimeout(property(camelContext, int.class, 
value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Map<String, Object> getAllOptions(Object target) {
+        return ALL_OPTIONS;
+    }
+
+    public static void clearBootstrapConfigurers() {
+        ALL_OPTIONS.clear();
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "customclassnames":
+        case "customClassNames": return java.lang.String.class;
+        case "enabled": return boolean.class;
+        case "environmentvariableexists":
+        case "environmentVariableExists": return java.lang.String.class;
+        case "failontimeout":
+        case "failOnTimeout": return boolean.class;
+        case "fileexists":
+        case "fileExists": return java.lang.String.class;
+        case "interval": return int.class;
+        case "timeout": return int.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.main.StartupConditionConfigurationProperties target = 
(org.apache.camel.main.StartupConditionConfigurationProperties) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "customclassnames":
+        case "customClassNames": return target.getCustomClassNames();
+        case "enabled": return target.isEnabled();
+        case "environmentvariableexists":
+        case "environmentVariableExists": return 
target.getEnvironmentVariableExists();
+        case "failontimeout":
+        case "failOnTimeout": return target.isFailOnTimeout();
+        case "fileexists":
+        case "fileExists": return target.getFileExists();
+        case "interval": return target.getInterval();
+        case "timeout": return target.getTimeout();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 934f069bb93..77580418ad4 100644
--- 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -1,6 +1,7 @@
 {
   "groups": [
     { "name": "camel.main", "description": "Camel Main configurations", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties" },
+    { "name": "camel.startupcondition", "description": "Camel Startup 
Condition configurations", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties" },
     { "name": "camel.routecontroller", "description": "Camel Route Controller 
configurations", "sourceType": 
"org.apache.camel.main.RouteControllerConfigurationProperties" },
     { "name": "camel.server", "description": "Camel Embedded HTTP Server (only 
for standalone; not Spring Boot or Quarkus) configurations", "sourceType": 
"org.apache.camel.main.HttpServerConfigurationProperties" },
     { "name": "camel.debug", "description": "Camel Debugger configurations", 
"sourceType": "org.apache.camel.main.DebuggerConfigurationProperties" },
@@ -303,6 +304,13 @@
     { "name": "camel.ssl.trustAllCertificates", "description": "Allows to 
trust all SSL certificates without performing certificate validation. This can 
be used in development environment but may expose the system to security risks. 
Notice that if the trustAllCertificates option is set to true then the 
trustStore\/trustStorePassword options are not in use..", "sourceType": 
"org.apache.camel.main.SSLConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.ssl.trustStore", "description": "The trust store to load. 
The trust store is by default loaded from classpath. If you must load from file 
system, then use file: as prefix. file:nameOfFile (to refer to the file system) 
classpath:nameOfFile (to refer to the classpath; default) http:uri (to load the 
resource using HTTP) ref:nameOfBean (to lookup an existing KeyStore instance 
from the registry, for example for testing and development).", "sourceType": 
"org.apache.camel.m [...]
     { "name": "camel.ssl.trustStorePassword", "description": "Sets the SSL 
Truststore password.", "sourceType": 
"org.apache.camel.main.SSLConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.customClassNames", "description": "A 
list of custom class names (FQN). Multiple classes can be separated by comma.", 
"sourceType": "org.apache.camel.main.StartupConditionConfigurationProperties", 
"type": "string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.enabled", "description": "To enable 
using startup conditions", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": false },
+    { "name": "camel.startupcondition.environmentVariableExists", 
"description": "Wait for an environment variable with the given name to exists 
before continuing", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.failOnTimeout", "description": "Whether 
to fail if the check timed out. The default is to fail and throw an exception 
causing Camel to not be able to startup.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": true },
+    { "name": "camel.startupcondition.fileExists", "description": "Wait for a 
file with the given name to exists before continuing", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"string", "javaType": "java.lang.String" },
+    { "name": "camel.startupcondition.interval", "description": "Interval in 
millis between checking conditions.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"integer", "javaType": "int", "defaultValue": 100 },
+    { "name": "camel.startupcondition.timeout", "description": "Total timeout 
(in millis) for all startup conditions.", "sourceType": 
"org.apache.camel.main.StartupConditionConfigurationProperties", "type": 
"integer", "javaType": "int", "defaultValue": 10000 },
     { "name": "camel.threadpool.allowCoreThreadTimeOut", "description": "Sets 
default whether to allow core threads to timeout", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "boolean", 
"javaType": "java.lang.Boolean", "defaultValue": "false" },
     { "name": "camel.threadpool.config", "description": "Adds a configuration 
for a specific thread pool profile (inherits default values)", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "object", 
"javaType": "java.util.Map" },
     { "name": "camel.threadpool.keepAliveTime", "description": "Sets the 
default keep alive time for inactive threads", "sourceType": 
"org.apache.camel.main.ThreadPoolConfigurationProperties", "type": "integer", 
"javaType": "java.lang.Long" },
diff --git 
a/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.StartupConditionConfigurationProperties
 
b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.StartupConditionConfigurationProperties
new file mode 100644
index 00000000000..a34ce29d72b
--- /dev/null
+++ 
b/core/camel-main/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.main.StartupConditionConfigurationProperties
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.main.StartupConditionConfigurationPropertiesConfigurer
diff --git a/core/camel-main/src/main/docs/main.adoc 
b/core/camel-main/src/main/docs/main.adoc
index 2b3842148a2..3d37b5bb89e 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -149,6 +149,22 @@ The camel.main supports 122 options, which are listed 
below.
 |===
 
 
+=== Camel Startup Condition configurations
+The camel.startupcondition supports 7 options, which are listed below.
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *camel.startupcondition.custom{zwsp}ClassNames* | A list of custom class 
names (FQN). Multiple classes can be separated by comma. |  | String
+| *camel.startupcondition.enabled* | To enable using startup conditions | 
false | boolean
+| *camel.startupcondition.environment{zwsp}VariableExists* | Wait for an 
environment variable with the given name to exists before continuing |  | String
+| *camel.startupcondition.failOn{zwsp}Timeout* | Whether to fail if the check 
timed out. The default is to fail and throw an exception causing Camel to not 
be able to startup. | true | boolean
+| *camel.startupcondition.file{zwsp}Exists* | Wait for a file with the given 
name to exists before continuing |  | String
+| *camel.startupcondition.interval* | Interval in millis between checking 
conditions. | 100 | int
+| *camel.startupcondition.timeout* | Total timeout (in millis) for all startup 
conditions. | 10000 | int
+|===
+
+
 === Camel Route Controller configurations
 The camel.routecontroller supports 12 options, which are listed below.
 
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 b9647dfea2e..93a93d17502 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
@@ -81,6 +81,8 @@ import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.spi.RouteTemplateParameterSource;
 import org.apache.camel.spi.RoutesLoader;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.spi.StartupConditionStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.SupervisingRouteController;
 import org.apache.camel.support.CamelContextHelper;
@@ -101,6 +103,8 @@ import 
org.apache.camel.support.jsse.TrustManagersParameters;
 import org.apache.camel.support.scan.PackageScanHelper;
 import org.apache.camel.support.service.BaseService;
 import org.apache.camel.support.startup.BacklogStartupStepRecorder;
+import org.apache.camel.support.startup.EnvStartupCondition;
+import org.apache.camel.support.startup.FileStartupCondition;
 import org.apache.camel.support.startup.LoggingStartupStepRecorder;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.ObjectHelper;
@@ -537,6 +541,11 @@ public abstract class BaseMainSupport extends BaseService {
             recorder.endStep(step);
         }
 
+        // configure startup conditions
+        step = recorder.beginStep(BaseMainSupport.class, 
"autoConfigurationStartupConditions", "Auto Configure");
+        autoConfigurationStartupConditions(camelContext, 
autoConfiguredProperties);
+        recorder.endStep(step);
+
         // configure from main configuration properties
         step = recorder.beginStep(BaseMainSupport.class, 
"doConfigureCamelContextFromMainConfiguration", "Auto Configure");
         doConfigureCamelContextFromMainConfiguration(camelContext, 
mainConfigurationProperties, autoConfiguredProperties);
@@ -682,6 +691,92 @@ public abstract class BaseMainSupport extends BaseService {
         }
     }
 
+    protected void autoConfigurationStartupConditions(
+            CamelContext camelContext, OrderedLocationProperties 
autoConfiguredProperties)
+            throws Exception {
+        // load properties
+        OrderedLocationProperties prop = (OrderedLocationProperties) 
camelContext.getPropertiesComponent()
+                .loadProperties(name -> name.startsWith("camel."), 
MainHelper::optionKey);
+
+        // load properties from ENV (override existing)
+        if 
(mainConfigurationProperties.isAutoConfigurationEnvironmentVariablesEnabled()) {
+            Properties propENV
+                    = MainHelper.loadEnvironmentVariablesAsProperties(new 
String[] { "camel.startupcondition." });
+            if (!propENV.isEmpty()) {
+                prop.putAll("ENV", propENV);
+            }
+        }
+        // load properties from JVM (override existing)
+        if 
(mainConfigurationProperties.isAutoConfigurationSystemPropertiesEnabled()) {
+            Properties propJVM = 
MainHelper.loadJvmSystemPropertiesAsProperties(new String[] { 
"camel.startupcondition." });
+            if (!propJVM.isEmpty()) {
+                prop.putAll("SYS", propJVM);
+            }
+        }
+
+        OrderedLocationProperties properties = new OrderedLocationProperties();
+
+        for (String key : prop.stringPropertyNames()) {
+            if (key.startsWith("camel.startupcondition.")) {
+                int dot = key.indexOf('.', 22);
+                String option = dot == -1 ? "" : key.substring(dot + 1);
+                String value = prop.getProperty(key, "");
+                validateOptionAndValue(key, option, value);
+                String loc = prop.getLocation(key);
+                properties.put(loc, optionKey(option), value);
+            }
+        }
+
+        boolean forceDisabled = 
"false".equals(properties.getProperty("camel.startupcondition.enabled"));
+        boolean configurations = !properties.isEmpty();
+
+        if (!properties.isEmpty()) {
+            LOG.debug("Auto-configuring startup condition from loaded 
properties: {}", properties.size());
+            setPropertiesOnTarget(camelContext, 
mainConfigurationProperties.startupCondition(), properties,
+                    "camel.startupcondition.",
+                    mainConfigurationProperties.isAutoConfigurationFailFast(), 
true, autoConfiguredProperties);
+        }
+
+        // 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());
+            });
+        }
+
+        if (configurations || 
mainConfigurationProperties.startupCondition().isEnabled()) {
+            StartupConditionStrategy scs
+                    = 
camelContext.getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
+            // auto-enable if something is configured
+            if (forceDisabled) {
+                scs.setEnabled(false);
+            } else {
+                scs.setEnabled(true);
+            }
+            
scs.setInterval(mainConfigurationProperties.startupCondition().getInterval());
+            
scs.setTimeout(mainConfigurationProperties.startupCondition().getTimeout());
+            
scs.setFailOnTimeout(mainConfigurationProperties.startupCondition().isFailOnTimeout());
+            String env = 
mainConfigurationProperties.startupCondition().getEnvironmentVariableExists();
+            if (env != null) {
+                scs.addStartupCondition(new EnvStartupCondition(env));
+            }
+            String file = 
mainConfigurationProperties.startupCondition().getFileExists();
+            if (file != null) {
+                scs.addStartupCondition(new FileStartupCondition(env));
+            }
+            String classes = 
mainConfigurationProperties.startupCondition().getCustomClassNames();
+            if (classes != null) {
+                for (String fqn : classes.split(",")) {
+                    fqn = fqn.trim();
+                    Class<? extends StartupCondition> clazz
+                            = 
camelContext.getClassResolver().resolveMandatoryClass(fqn, 
StartupCondition.class);
+                    
scs.addStartupCondition(camelContext.getInjector().newInstance(clazz));
+                }
+            }
+        }
+    }
+
     protected void configureRoutesLoader(CamelContext camelContext) {
         // use main based routes loader
         ExtendedCamelContext ecc = camelContext.getCamelContextExtension();
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index efb5611c1cb..fcafc96f3d9 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -79,6 +79,7 @@ import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.StartupConditionStrategy;
 import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.ThreadPoolFactory;
@@ -354,6 +355,10 @@ public final class DefaultConfigurationConfigurer {
                     config.getRouteFilterIncludePattern(),
                     config.getRouteFilterExcludePattern());
         }
+
+        // check startup conditions before we can continue
+        StartupConditionStrategy scs = 
ecc.getContextPlugin(StartupConditionStrategy.class);
+        scs.checkStartupConditions();
     }
 
     /**
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 4327c3f7133..22804433b09 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -57,6 +57,7 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
 
     // extended configuration
     private HealthConfigurationProperties healthConfigurationProperties;
+    private StartupConditionConfigurationProperties 
startupConditionConfigurationProperties;
     private LraConfigurationProperties lraConfigurationProperties;
     private OtelConfigurationProperties otelConfigurationProperties;
     private MetricsConfigurationProperties metricsConfigurationProperties;
@@ -156,6 +157,16 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
         return healthConfigurationProperties;
     }
 
+    /**
+     * To configure startup conditions
+     */
+    public StartupConditionConfigurationProperties startupCondition() {
+        if (startupConditionConfigurationProperties == null) {
+            startupConditionConfigurationProperties = new 
StartupConditionConfigurationProperties(this);
+        }
+        return startupConditionConfigurationProperties;
+    }
+
     /**
      * Whether there has been any health check configuration specified
      */
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/StartupConditionConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/StartupConditionConfigurationProperties.java
new file mode 100644
index 00000000000..3107d37c777
--- /dev/null
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/StartupConditionConfigurationProperties.java
@@ -0,0 +1,194 @@
+/*
+ * 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 org.apache.camel.spi.BootstrapCloseable;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Configuration for startup conditions
+ */
+@Configurer(bootstrap = true, extended = true)
+public class StartupConditionConfigurationProperties implements 
BootstrapCloseable {
+
+    private MainConfigurationProperties parent;
+
+    @Metadata(defaultValue = "false")
+    private boolean enabled;
+    @Metadata(defaultValue = "100")
+    private int interval = 100;
+    @Metadata(defaultValue = "10000")
+    private int timeout = 10000;
+    @Metadata(defaultValue = "true")
+    private boolean failOnTimeout = true;
+    @Metadata
+    private String environmentVariableExists;
+    @Metadata
+    private String fileExists;
+    @Metadata
+    private String customClassNames;
+
+    public StartupConditionConfigurationProperties(MainConfigurationProperties 
parent) {
+        this.parent = parent;
+    }
+
+    public MainConfigurationProperties end() {
+        return parent;
+    }
+
+    @Override
+    public void close() {
+        parent = null;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    /**
+     * To enable using startup conditions
+     */
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public int getInterval() {
+        return interval;
+    }
+
+    /**
+     * Interval in millis between checking conditions.
+     */
+    public void setInterval(int interval) {
+        this.interval = interval;
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * Total timeout (in millis) for all startup conditions.
+     */
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    public boolean isFailOnTimeout() {
+        return failOnTimeout;
+    }
+
+    /**
+     * Whether to fail if the check timed out. The default is to fail and 
throw an exception causing Camel to not be
+     * able to startup.
+     */
+    public void setFailOnTimeout(boolean failOnTimeout) {
+        this.failOnTimeout = failOnTimeout;
+    }
+
+    public String getEnvironmentVariableExists() {
+        return environmentVariableExists;
+    }
+
+    /**
+     * Wait for an environment variable with the given name to exists before 
continuing
+     */
+    public void setEnvironmentVariableExists(String environmentVariableExists) 
{
+        this.environmentVariableExists = environmentVariableExists;
+    }
+
+    public String getFileExists() {
+        return fileExists;
+    }
+
+    /**
+     * Wait for a file with the given name to exists before continuing
+     */
+    public void setFileExists(String fileExists) {
+        this.fileExists = fileExists;
+    }
+
+    public String getCustomClassNames() {
+        return customClassNames;
+    }
+
+    /**
+     * A list of custom class names (FQN). Multiple classes can be separated 
by comma.
+     */
+    public void setCustomClassNames(String customClassNames) {
+        this.customClassNames = customClassNames;
+    }
+
+    /**
+     * To enable using startup conditions
+     */
+    public StartupConditionConfigurationProperties withEnabled(boolean 
enabled) {
+        this.enabled = enabled;
+        return this;
+    }
+
+    /**
+     * Interval in millis between checking startup conditions
+     */
+    public StartupConditionConfigurationProperties withInterval(int interval) {
+        this.interval = interval;
+        return this;
+    }
+
+    /**
+     * Total timeout (in millis) for all startup conditions.
+     */
+    public StartupConditionConfigurationProperties withTimeout(int timeout) {
+        this.timeout = timeout;
+        return this;
+    }
+
+    /**
+     * Whether to fail if the check timed out. The default is to fail and 
throw an exception causing Camel to not be
+     * able to startup.
+     */
+    public StartupConditionConfigurationProperties withFailOnTimeout(boolean 
failOnTimeout) {
+        this.failOnTimeout = failOnTimeout;
+        return this;
+    }
+
+    /**
+     * Wait for an environment variable with the given name to exists before 
continuing
+     */
+    public StartupConditionConfigurationProperties 
withEnvironmentVariableExists(String environmentVariableExists) {
+        this.environmentVariableExists = environmentVariableExists;
+        return this;
+    }
+
+    /**
+     * Wait for a file with the given name to exists before continuing
+     */
+    public StartupConditionConfigurationProperties withFileExists(String 
fileExists) {
+        this.fileExists = fileExists;
+        return this;
+    }
+
+    /**
+     * A list of custom class names (FQN). Multiple classes can be separated 
by comma.
+     */
+    public StartupConditionConfigurationProperties withCustomClassNames(String 
customClassNames) {
+        this.customClassNames = customClassNames;
+        return this;
+    }
+
+}
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionEnvTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionEnvTest.java
new file mode 100644
index 00000000000..60e67f5440d
--- /dev/null
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionEnvTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.support.startup.EnvStartupCondition;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class MainStartupConditionEnvTest {
+
+    private static final AtomicInteger COUNTER = new AtomicInteger();
+
+    @Test
+    public void testCustomCondition() {
+        Main main = new Main();
+        try {
+            main.configure().startupCondition().withEnabled(true)
+                    
.withCustomClassNames("org.apache.camel.main.MainStartupConditionEnvTest$MyEnvCondition");
+            main.start();
+
+            Assertions.assertEquals(3, COUNTER.get());
+        } finally {
+            main.stop();
+        }
+    }
+
+    public static class MyEnvCondition extends EnvStartupCondition {
+
+        public MyEnvCondition() {
+            super("MY_ENV");
+        }
+
+        @Override
+        protected String lookupEnvironmentVariable(String env) {
+            if (COUNTER.incrementAndGet() < 3) {
+                return null;
+            }
+            return "FOO";
+        }
+    }
+}
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTest.java
new file mode 100644
index 00000000000..0d284e6d1aa
--- /dev/null
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.StartupCondition;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class MainStartupConditionTest {
+
+    @Test
+    public void testCustomCondition() {
+        Main main = new Main();
+        try {
+            
main.configure().withRoutesBuilderClasses("org.apache.camel.main.MainStartupConditionTest$MyRoute");
+            
main.configure().startupCondition().withEnabled(true).withTimeout(250).withInterval(100)
+                    
.withCustomClassNames("org.apache.camel.main.MainStartupConditionTest$MyCondition");
+            main.start();
+            fail("Should throw exception");
+        } catch (Exception e) {
+            Assertions.assertEquals("Startup condition timeout error", 
e.getCause().getMessage());
+        } finally {
+            main.stop();
+        }
+    }
+
+    public static class MyCondition implements StartupCondition {
+
+        @Override
+        public boolean canContinue(CamelContext camelContext) throws Exception 
{
+            return false;
+        }
+    }
+
+    public static class MyRoute extends RouteBuilder {
+
+        @Override
+        public void configure() throws Exception {
+            from("direct:start")
+                    .to("mock:result");
+        }
+    }
+
+}
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTimeoutTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTimeoutTest.java
new file mode 100644
index 00000000000..b7ed5372f62
--- /dev/null
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainStartupConditionTimeoutTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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 org.apache.camel.support.startup.EnvStartupCondition;
+import org.apache.camel.util.StopWatch;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class MainStartupConditionTimeoutTest {
+
+    @Test
+    public void testCustomCondition() {
+        StopWatch watch = new StopWatch();
+        Main main = new Main();
+        try {
+            main.configure().startupCondition().withEnabled(true)
+                    .withTimeout(250)
+                    
.withCustomClassNames("org.apache.camel.main.MainStartupConditionTimeoutTest$MyEnvCondition");
+            main.start();
+            fail("Should throw exception");
+        } catch (Exception e) {
+            Assertions.assertEquals(
+                    "Startup condition: ENV cannot continue due to: OS 
Environment Variable: MY_ENV does not exist",
+                    e.getCause().getMessage());
+        } finally {
+            main.stop();
+        }
+        Assertions.assertTrue(watch.taken() < 3000);
+    }
+
+    public static class MyEnvCondition extends EnvStartupCondition {
+
+        public MyEnvCondition() {
+            super("MY_ENV");
+        }
+
+        @Override
+        protected String lookupEnvironmentVariable(String env) {
+            return null;
+        }
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/startup/EnvStartupCondition.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/EnvStartupCondition.java
new file mode 100644
index 00000000000..b62a8a74775
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/EnvStartupCondition.java
@@ -0,0 +1,61 @@
+/*
+ * 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.support.startup;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Startup condition that waits for an ENV variable to exists.
+ */
+public class EnvStartupCondition implements StartupCondition {
+
+    private final String env;
+
+    public EnvStartupCondition(String env) {
+        ObjectHelper.notNullOrEmpty(env, "ENV");
+        this.env = env;
+    }
+
+    @Override
+    public String getName() {
+        return "ENV";
+    }
+
+    @Override
+    public String getWaitMessage() {
+        return "Waiting for OS Environment Variable: " + env;
+    }
+
+    @Override
+    public String getFailureMessage() {
+        return "OS Environment Variable: " + env + " does not exist";
+    }
+
+    protected String lookupEnvironmentVariable(String env) {
+        return IOHelper.lookupEnvironmentVariable(env);
+    }
+
+    @Override
+    public boolean canContinue(CamelContext camelContext) throws Exception {
+        String value = lookupEnvironmentVariable(env);
+        return ObjectHelper.isNotEmpty(value);
+    }
+
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/startup/FileStartupCondition.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/FileStartupCondition.java
new file mode 100644
index 00000000000..5128c812e75
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/FileStartupCondition.java
@@ -0,0 +1,61 @@
+/*
+ * 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.support.startup;
+
+import java.io.File;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.StartupCondition;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Startup condition that waits for a file to exists.
+ */
+public class FileStartupCondition implements StartupCondition {
+
+    private final File file;
+
+    public FileStartupCondition(String name) {
+        ObjectHelper.notNullOrEmpty(name, "File");
+        this.file = new File(name);
+    }
+
+    @Override
+    public String getName() {
+        return "File";
+    }
+
+    @Override
+    public String getWaitMessage() {
+        return "Waiting for file: " + file;
+    }
+
+    @Override
+    public String getFailureMessage() {
+        return "File: " + file + " does not exist";
+    }
+
+    protected boolean fileExists(File file) {
+        return file.exists();
+    }
+
+    @Override
+    public boolean canContinue(CamelContext camelContext) throws Exception {
+        return fileExists(file);
+    }
+
+}
diff --git a/docs/user-manual/modules/ROOT/nav.adoc 
b/docs/user-manual/modules/ROOT/nav.adoc
index 60b6c1a0335..3bfbce66340 100644
--- a/docs/user-manual/modules/ROOT/nav.adoc
+++ b/docs/user-manual/modules/ROOT/nav.adoc
@@ -84,6 +84,7 @@
 ** xref:route-reload.adoc[RouteReload]
 ** xref:route-template.adoc[RouteTemplate]
 ** xref:routes.adoc[Routes]
+** xref:startup-condition.adoc[Startup Condition]
 ** xref:stream-caching.adoc[Stream caching]
 ** xref:transformer.adoc[Transformer]
 ** xref:threading-model.adoc[Threading Model]
diff --git a/docs/user-manual/modules/ROOT/pages/lifecycle.adoc 
b/docs/user-manual/modules/ROOT/pages/lifecycle.adoc
index 2d555f71b70..aa238f93294 100644
--- a/docs/user-manual/modules/ROOT/pages/lifecycle.adoc
+++ b/docs/user-manual/modules/ROOT/pages/lifecycle.adoc
@@ -59,3 +59,9 @@ TIP: A service can optimally support suspend/resume by the
 Camel supports suspension. It's encouraged that consumers support
 suspension which allows suspending/resuming routes.
 
+== Startup Lifecycle
+
+When Camel startup there are various listeners that can be used to plugin 
custom code, that
+can listen and react during startup such as `LifecycleStrategy`, or 
`MainListener`.
+
+If you need Camel to check for _something_ before it can start up, then look 
at xref:startup-condition.adoc[Startup Condition]
\ No newline at end of file
diff --git a/docs/user-manual/modules/ROOT/pages/startup-condition.adoc 
b/docs/user-manual/modules/ROOT/pages/startup-condition.adoc
new file mode 100644
index 00000000000..a337b3f713b
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/startup-condition.adoc
@@ -0,0 +1,40 @@
+= Startup Condition
+
+*Available as of Camel 4.9*
+
+You can use `StartupCondition` to let Camel perform some checks on startup,
+before continuing. For example to check if a specific ENV exists, or wait
+for a specific file to be created etc.
+
+Camel provides a few out of the box
+
+- `EnvStartupCondition` - To check for a specific OS environment exists
+- `FileStartupCondition` - To check for a specific file exists
+
+You can implement custom conditions by implementing 
`org.apache.camel.spi.StartupCondition`,
+and add these to the `StartupConditionStrategy` or `Registry` such as:
+
+[source,java]
+----
+StartupConditionStrategy scs = 
context.getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
+scs.addStartupCondition(new MyCondition());
+----
+
+If you use Camel Main, Spring Boot, or Quarkus, you can configure startup 
conditions with configuration in `application.properties`.
+
+For example to check for a specific OS environment variable exists:
+
+[source,properties]
+----
+camel.startupcondition.enabled = true
+camel.startupcondition.environmentVariableExists = FOO_BAR
+----
+
+Or to use a custom condition by its class name:
+
+[source,properties]
+----
+camel.startupcondition.enabled = true
+camel.startupcondition.customClassNames = com.foo.MyStartupCondition
+----
+
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
index dae9af3d9eb..d27e4030f31 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainMojo.java
@@ -209,9 +209,10 @@ public class PrepareCamelMainMojo extends 
AbstractGeneratorMojo {
                     prefix = "camel.vault.kubernetes.";
                 } else if (file.getName().contains("HashicorpVault")) {
                     prefix = "camel.vault.hashicorp.";
-                    // TODO: add more vault providers here
                 } else if (file.getName().contains("Health")) {
                     prefix = "camel.health.";
+                } else if (file.getName().contains("StartupCondition")) {
+                    prefix = "camel.startupcondition.";
                 } else if (file.getName().contains("Lra")) {
                     prefix = "camel.lra.";
                 } else if (file.getName().contains("Otel")) {
@@ -319,6 +320,9 @@ public class PrepareCamelMainMojo extends 
AbstractGeneratorMojo {
             model.getOptions().addAll(data);
             model.getGroups().add(new MainGroupModel(
                     "camel.main", "Camel Main configurations", 
"org.apache.camel.main.DefaultConfigurationProperties"));
+            model.getGroups().add(new MainGroupModel(
+                    "camel.startupcondition", "Camel Startup Condition 
configurations",
+                    
"org.apache.camel.main.StartupConditionConfigurationProperties"));
             model.getGroups()
                     .add(new MainGroupModel(
                             "camel.routecontroller", "Camel Route Controller 
configurations",
@@ -369,7 +373,6 @@ public class PrepareCamelMainMojo extends 
AbstractGeneratorMojo {
                     new MainGroupModel(
                             "camel.vault.hashicorp", "Camel Hashicorp Vault 
configurations",
                             
"org.apache.camel.vault.HashicorpVaultConfiguration"));
-            // TODO: add more vault providers here
             model.getGroups().add(new MainGroupModel(
                     "camel.opentelemetry", "Camel OpenTelemetry 
configurations",
                     "org.apache.camel.main.OtelConfigurationProperties"));

Reply via email to