You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/08/15 06:53:26 UTC

[camel] branch main updated: CAMEL-19739: camel run - Add stub option to run in stub mode (#11107)

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 0011505773c CAMEL-19739: camel run - Add stub option to run in stub mode (#11107)
0011505773c is described below

commit 0011505773c25397bafbdaf1376134d0f0878b2e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Aug 15 08:53:20 2023 +0200

    CAMEL-19739: camel run - Add stub option to run in stub mode (#11107)
    
    CAMEL-19739: camel run - Add stub option to run in stub mode
---
 .../org/apache/camel/catalog/components/stub.json  | 21 +++---
 .../component/stub/StubComponentConfigurer.java    |  6 ++
 .../org/apache/camel/component/stub/stub.json      | 21 +++---
 .../apache/camel/component/stub/StubComponent.java | 36 +++++++--
 .../org/apache/camel/main/BaseMainSupport.java     | 10 ++-
 .../camel/main/MainAutowiredLifecycleStrategy.java | 30 ++++----
 .../modules/ROOT/pages/camel-jbang.adoc            | 47 ++++++++++++
 .../component/dsl/StubComponentBuilderFactory.java | 17 +++++
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 28 ++++++-
 .../camel/dsl/jbang/core/common/CatalogLoader.java |  3 +-
 .../java/org/apache/camel/main/KameletMain.java    | 58 ++++++++++-----
 .../DependencyDownloaderComponentResolver.java     | 18 +++--
 .../KameletAutowiredLifecycleStrategy.java         | 85 ++++++++++++++++++++++
 .../camel/main/download/KameletMainInjector.java   | 62 ++++++++++------
 14 files changed, 351 insertions(+), 91 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json
index 40d00e7f9b4..ead3c9691af 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json
@@ -23,16 +23,17 @@
   },
   "componentProperties": {
     "shadow": { "index": 0, "kind": "property", "displayName": "Shadow", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If shadow is enabled then the stub component will register a shadow endpoint with the actual uri that refers to the stub endpoint, meaning you can lookup the endpoint via both stub:kafka:cheese and kafka:cheese." },
-    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be proce [...]
-    "concurrentConsumers": { "index": 2, "kind": "property", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the default number of concurrent threads processing exchanges." },
-    "defaultPollTimeout": { "index": 3, "kind": "property", "displayName": "Default Poll Timeout", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The timeout (in milliseconds) used when polling. When a timeout occurs, the consumer can check whether it is allowed to continue running. Setting a lower value allows the consume [...]
-    "defaultBlockWhenFull": { "index": 4, "kind": "property", "displayName": "Default Block When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is fu [...]
-    "defaultDiscardWhenFull": { "index": 5, "kind": "property", "displayName": "Default Discard When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will be discarded. By default, an exception will be thrown stating that the queue is full. By enabling this option, the callin [...]
-    "defaultOfferTimeout": { "index": 6, "kind": "property", "displayName": "Default Offer Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is full. By enabling this option,  [...]
-    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
-    "defaultQueueFactory": { "index": 9, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory<org.apache.camel.Exchange>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." },
-    "queueSize": { "index": 10, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." }
+    "shadowPattern": { "index": 1, "kind": "property", "displayName": "Shadow Pattern", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "If shadow is enabled then this pattern can be used to filter which components to match. Multiple patterns can be separated by comma." },
+    "bridgeErrorHandler": { "index": 2, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be proce [...]
+    "concurrentConsumers": { "index": 3, "kind": "property", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the default number of concurrent threads processing exchanges." },
+    "defaultPollTimeout": { "index": 4, "kind": "property", "displayName": "Default Poll Timeout", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The timeout (in milliseconds) used when polling. When a timeout occurs, the consumer can check whether it is allowed to continue running. Setting a lower value allows the consume [...]
+    "defaultBlockWhenFull": { "index": 5, "kind": "property", "displayName": "Default Block When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is fu [...]
+    "defaultDiscardWhenFull": { "index": 6, "kind": "property", "displayName": "Default Discard When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will be discarded. By default, an exception will be thrown stating that the queue is full. By enabling this option, the callin [...]
+    "defaultOfferTimeout": { "index": 7, "kind": "property", "displayName": "Default Offer Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is full. By enabling this option,  [...]
+    "lazyStartProducer": { "index": 8, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 9, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "defaultQueueFactory": { "index": 10, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory<org.apache.camel.Exchange>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." },
+    "queueSize": { "index": 11, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." }
   },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" },
diff --git a/components/camel-stub/src/generated/java/org/apache/camel/component/stub/StubComponentConfigurer.java b/components/camel-stub/src/generated/java/org/apache/camel/component/stub/StubComponentConfigurer.java
index 789ce31c8b1..07bdfe0aa7c 100644
--- a/components/camel-stub/src/generated/java/org/apache/camel/component/stub/StubComponentConfigurer.java
+++ b/components/camel-stub/src/generated/java/org/apache/camel/component/stub/StubComponentConfigurer.java
@@ -22,6 +22,8 @@ public class StubComponentConfigurer extends SedaComponentConfigurer implements
         StubComponent target = (StubComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "shadow": target.setShadow(property(camelContext, boolean.class, value)); return true;
+        case "shadowpattern":
+        case "shadowPattern": target.setShadowPattern(property(camelContext, java.lang.String.class, value)); return true;
         default: return true;
         }
     }
@@ -30,6 +32,8 @@ public class StubComponentConfigurer extends SedaComponentConfigurer implements
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "shadow": return boolean.class;
+        case "shadowpattern":
+        case "shadowPattern": return java.lang.String.class;
         default: return super.getOptionType(name, ignoreCase);
         }
     }
@@ -39,6 +43,8 @@ public class StubComponentConfigurer extends SedaComponentConfigurer implements
         StubComponent target = (StubComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "shadow": return target.isShadow();
+        case "shadowpattern":
+        case "shadowPattern": return target.getShadowPattern();
         default: return super.getOptionValue(obj, name, ignoreCase);
         }
     }
diff --git a/components/camel-stub/src/generated/resources/org/apache/camel/component/stub/stub.json b/components/camel-stub/src/generated/resources/org/apache/camel/component/stub/stub.json
index 40d00e7f9b4..ead3c9691af 100644
--- a/components/camel-stub/src/generated/resources/org/apache/camel/component/stub/stub.json
+++ b/components/camel-stub/src/generated/resources/org/apache/camel/component/stub/stub.json
@@ -23,16 +23,17 @@
   },
   "componentProperties": {
     "shadow": { "index": 0, "kind": "property", "displayName": "Shadow", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If shadow is enabled then the stub component will register a shadow endpoint with the actual uri that refers to the stub endpoint, meaning you can lookup the endpoint via both stub:kafka:cheese and kafka:cheese." },
-    "bridgeErrorHandler": { "index": 1, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be proce [...]
-    "concurrentConsumers": { "index": 2, "kind": "property", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the default number of concurrent threads processing exchanges." },
-    "defaultPollTimeout": { "index": 3, "kind": "property", "displayName": "Default Poll Timeout", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The timeout (in milliseconds) used when polling. When a timeout occurs, the consumer can check whether it is allowed to continue running. Setting a lower value allows the consume [...]
-    "defaultBlockWhenFull": { "index": 4, "kind": "property", "displayName": "Default Block When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is fu [...]
-    "defaultDiscardWhenFull": { "index": 5, "kind": "property", "displayName": "Default Discard When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will be discarded. By default, an exception will be thrown stating that the queue is full. By enabling this option, the callin [...]
-    "defaultOfferTimeout": { "index": 6, "kind": "property", "displayName": "Default Offer Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is full. By enabling this option,  [...]
-    "lazyStartProducer": { "index": 7, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
-    "autowiredEnabled": { "index": 8, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
-    "defaultQueueFactory": { "index": 9, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory<org.apache.camel.Exchange>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." },
-    "queueSize": { "index": 10, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." }
+    "shadowPattern": { "index": 1, "kind": "property", "displayName": "Shadow Pattern", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "If shadow is enabled then this pattern can be used to filter which components to match. Multiple patterns can be separated by comma." },
+    "bridgeErrorHandler": { "index": 2, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be proce [...]
+    "concurrentConsumers": { "index": 3, "kind": "property", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "description": "Sets the default number of concurrent threads processing exchanges." },
+    "defaultPollTimeout": { "index": 4, "kind": "property", "displayName": "Default Poll Timeout", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The timeout (in milliseconds) used when polling. When a timeout occurs, the consumer can check whether it is allowed to continue running. Setting a lower value allows the consume [...]
+    "defaultBlockWhenFull": { "index": 5, "kind": "property", "displayName": "Default Block When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is fu [...]
+    "defaultDiscardWhenFull": { "index": 6, "kind": "property", "displayName": "Default Discard When Full", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether a thread that sends messages to a full SEDA queue will be discarded. By default, an exception will be thrown stating that the queue is full. By enabling this option, the callin [...]
+    "defaultOfferTimeout": { "index": 7, "kind": "property", "displayName": "Default Offer Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Whether a thread that sends messages to a full SEDA queue will block until the queue's capacity is no longer exhausted. By default, an exception will be thrown stating that the queue is full. By enabling this option,  [...]
+    "lazyStartProducer": { "index": 8, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+    "autowiredEnabled": { "index": 9, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+    "defaultQueueFactory": { "index": 10, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory<org.apache.camel.Exchange>", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." },
+    "queueSize": { "index": 11, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." }
   },
   "properties": {
     "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" },
diff --git a/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubComponent.java b/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubComponent.java
index fe333c74930..a79b81e6cfa 100644
--- a/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubComponent.java
+++ b/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubComponent.java
@@ -19,17 +19,18 @@ package org.apache.camel.component.stub;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.Exchange;
 import org.apache.camel.component.seda.BlockingQueueFactory;
 import org.apache.camel.component.seda.SedaComponent;
 import org.apache.camel.spi.EndpointRegistry;
 import org.apache.camel.spi.Metadata;
+import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.NormalizedUri;
 
 /**
- * The <a href="http://camel.apache.org/stub.html">Stub Component</a> is for stubbing out endpoints while developing or
- * testing.
+ * The stub component is for stubbing out endpoints while developing or testing.
  *
  * Allows you to easily stub out a middleware transport by prefixing the URI with "stub:" which is handy for testing out
  * routes, or isolating bits of middleware.
@@ -39,6 +40,8 @@ public class StubComponent extends SedaComponent {
 
     @Metadata
     private boolean shadow;
+    @Metadata
+    private String shadowPattern;
 
     public StubComponent() {
     }
@@ -89,6 +92,20 @@ public class StubComponent extends SedaComponent {
         this.shadow = shadow;
     }
 
+    public String getShadowPattern() {
+        return shadowPattern;
+    }
+
+    /**
+     * If shadow is enabled then this pattern can be used to filter which components to match. Multiple patterns can be
+     * separated by comma.
+     *
+     * @see org.apache.camel.support.EndpointHelper#matchEndpoint(CamelContext, String, String)
+     */
+    public void setShadowPattern(String shadowPattern) {
+        this.shadowPattern = shadowPattern;
+    }
+
     @Override
     protected void doInit() throws Exception {
         super.doInit();
@@ -96,12 +113,15 @@ public class StubComponent extends SedaComponent {
         if (shadow) {
             final EndpointRegistry registry = getCamelContext().getEndpointRegistry();
             getCamelContext().getCamelContextExtension().registerEndpointCallback((uri, endpoint) -> {
-                String shadowUri = resolveShadowUri(uri);
-                if (!uri.equals(shadowUri)) {
-                    NormalizedUri nuri = NormalizedUri.newNormalizedUri(shadowUri, false);
-                    // put the shadow uri directly into the endpoint registry,
-                    // so we can lookup the stubbed endpoint using its actual uri
-                    registry.put(nuri, endpoint);
+                boolean match = shadowPattern == null || EndpointHelper.matchEndpoint(getCamelContext(), uri, shadowPattern);
+                if (match) {
+                    String shadowUri = resolveShadowUri(uri);
+                    if (!uri.equals(shadowUri)) {
+                        NormalizedUri nuri = NormalizedUri.newNormalizedUri(shadowUri, false);
+                        // put the shadow uri directly into the endpoint registry,
+                        // so we can lookup the stubbed endpoint using its actual uri
+                        registry.put(nuri, endpoint);
+                    }
                 }
                 return endpoint;
             });
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 245982c4315..715669b8102 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
@@ -57,6 +57,7 @@ import org.apache.camel.spi.CamelEvent;
 import org.apache.camel.spi.ContextReloadStrategy;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LifecycleStrategy;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PeriodTaskScheduler;
 import org.apache.camel.spi.PropertiesComponent;
@@ -586,13 +587,20 @@ public abstract class BaseMainSupport extends BaseService {
         return configurer;
     }
 
+    /**
+     * A specialized {@link LifecycleStrategy} that can handle autowiring of Camel components, dataformats, languages.
+     */
+    protected LifecycleStrategy createLifecycleStrategy(CamelContext camelContext) {
+        return new MainAutowiredLifecycleStrategy(camelContext);
+    }
+
     protected void postProcessCamelContext(CamelContext camelContext) throws Exception {
         // gathers the properties (key=value) that was used as property placeholders during bootstrap
         final OrderedLocationProperties propertyPlaceholders = new OrderedLocationProperties();
 
         // use the main autowired lifecycle strategy instead of the default
         camelContext.getLifecycleStrategies().removeIf(s -> s instanceof AutowiredLifecycleStrategy);
-        camelContext.addLifecycleStrategy(new MainAutowiredLifecycleStrategy(camelContext));
+        camelContext.addLifecycleStrategy(createLifecycleStrategy(camelContext));
 
         // setup properties
         configurePropertiesService(camelContext);
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainAutowiredLifecycleStrategy.java b/core/camel-main/src/main/java/org/apache/camel/main/MainAutowiredLifecycleStrategy.java
index d318b06ddd6..d6074a10574 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainAutowiredLifecycleStrategy.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainAutowiredLifecycleStrategy.java
@@ -27,13 +27,9 @@ import org.apache.camel.spi.AutowiredLifecycleStrategy;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.Language;
 import org.apache.camel.support.LifecycleStrategySupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public class MainAutowiredLifecycleStrategy extends LifecycleStrategySupport implements AutowiredLifecycleStrategy, Ordered {
 
-    private static final Logger LOG = LoggerFactory.getLogger(MainAutowiredLifecycleStrategy.class);
-
     // provisional maps to hold components, dataformats, languages that are created during
     // starting camel, but need to defer autowiring until later in case additional configuration
     // would turn off autowired for some components
@@ -100,26 +96,34 @@ public class MainAutowiredLifecycleStrategy extends LifecycleStrategySupport imp
         }
     }
 
+    protected boolean isEnabled(String name, Component component) {
+        return camelContext.isAutowiredEnabled() && component.isAutowiredEnabled();
+    }
+
+    protected boolean isEnabled(String name, Language language) {
+        // autowiring can be turned off on context level
+        return camelContext.isAutowiredEnabled();
+    }
+
+    protected boolean isEnabled(String name, DataFormat dataFormat) {
+        // autowiring can be turned off on context level
+        return camelContext.isAutowiredEnabled();
+    }
+
     private void autowireComponent(String name, Component component) {
-        // autowiring can be turned off on context level and per component
-        boolean enabled = camelContext.isAutowiredEnabled() && component.isAutowiredEnabled();
-        if (enabled) {
+        if (isEnabled(name, component)) {
             autowire(name, "component", component);
         }
     }
 
     private void autowireDataFormat(String name, DataFormat dataFormat) {
-        // autowiring can be turned off on context level
-        boolean enabled = camelContext.isAutowiredEnabled();
-        if (enabled) {
+        if (isEnabled(name, dataFormat)) {
             autowire(name, "dataformat", dataFormat);
         }
     }
 
     private void autowireLanguage(String name, Language language) {
-        // autowiring can be turned off on context level
-        boolean enabled = camelContext.isAutowiredEnabled();
-        if (enabled) {
+        if (isEnabled(name, language)) {
             autowire(name, "language", language);
         }
     }
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 36375fefdae..39d70b7e4f8 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -214,6 +214,53 @@ camel run --source-dir=mycode
 
 This starts Camel where it will load the files from the _source dir_ (also sub folders).
 
+=== Stub components that should not be active
+
+Sometimes you need to troubleshoot an existing integration and is given some Camel code (routes).
+These routes may use different components, and those components may be tricky to run as they are configured
+in a custom way, or need connection to servers you may not have access too.
+
+You can run Camel JBang by stubbing those components (or all of them).
+
+For example suppose you need access to a JMS broker in the given route below.
+
+[source,java]
+----
+from("jms:inbox")
+  .log("Incoming order")
+  .to("bean:transform")
+  .log("After transformation")
+  .to("jms:process");
+----
+
+Then you can run this by stub the `jms` component by:
+
+[source,bash]
+----
+camel run syncToDatabase.java --stub=jms
+----
+
+Then Camel will not start up the JMS component but replace it with the `stub` component, but keep the actual endpoint URIs.
+
+You can then simulate sending messages to Camel with the `cmd send` command:
+
+[source,bash]
+----
+camel cmd send --body='Something here'
+----
+
+Which then will send the message to the incoming endpoint in the route, i.e. `jms:inbox` which has been stubbed.
+
+You can also stub a specific endpoint by providing the full uri, such as:
+
+[source,bash]
+----
+camel run syncToDatabase.java --stub=jms:inbox
+----
+
+Then only the `jms:inbox` endpoint is stubbed.
+
+TIP: You can stub multiple components separated by comma, such as `--stub=jms,sql`
 
 === Dev mode with live reload
 
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/StubComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/StubComponentBuilderFactory.java
index df8560278ec..8d4f78bc2a3 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/StubComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/StubComponentBuilderFactory.java
@@ -66,6 +66,22 @@ public interface StubComponentBuilderFactory {
             doSetProperty("shadow", shadow);
             return this;
         }
+        /**
+         * If shadow is enabled then this pattern can be used to filter which
+         * components to match. Multiple patterns can be separated by comma.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: common
+         * 
+         * @param shadowPattern the value to set
+         * @return the dsl builder
+         */
+        default StubComponentBuilder shadowPattern(
+                java.lang.String shadowPattern) {
+            doSetProperty("shadowPattern", shadowPattern);
+            return this;
+        }
         /**
          * Allows for bridging the consumer to the Camel routing Error Handler,
          * which mean any exceptions occurred while the consumer is trying to
@@ -274,6 +290,7 @@ public interface StubComponentBuilderFactory {
                 Object value) {
             switch (name) {
             case "shadow": ((StubComponent) component).setShadow((boolean) value); return true;
+            case "shadowPattern": ((StubComponent) component).setShadowPattern((java.lang.String) value); return true;
             case "bridgeErrorHandler": ((StubComponent) component).setBridgeErrorHandler((boolean) value); return true;
             case "concurrentConsumers": ((StubComponent) component).setConcurrentConsumers((int) value); return true;
             case "defaultPollTimeout": ((StubComponent) component).setDefaultPollTimeout((int) value); return true;
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 6e56380f37b..95b6ce49c96 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -204,6 +204,10 @@ public class Run extends CamelCommand {
     @Option(names = { "-p", "--prop", "--property" }, description = "Additional properties (override existing)", arity = "0")
     String[] property;
 
+    @Option(names = { "--stub" }, description = "Stubs all the matching endpoint with the given component name or pattern."
+                                                + " Multiple names can be separated by comma. (all = everything).")
+    String stub;
+
     @Option(names = { "--jfr" },
             description = "Enables Java Flight Recorder saving recording to disk on exit")
     boolean jfr;
@@ -367,6 +371,26 @@ public class Run extends CamelCommand {
         main.setDownloadListener(new RunDownloadListener());
         main.setAppName("Apache Camel (JBang)");
 
+        if (stub != null) {
+            if ("all".equals(stub)) {
+                stub = "*";
+            }
+            // we need to match by wildcard, to make it easier
+            StringJoiner sj = new StringJoiner(",");
+            for (String n : stub.split(",")) {
+                // you can either refer to a name or a specific endpoint
+                // if there is a colon then we assume its a specific endpoint then we should not add wildcard
+                boolean colon = n.contains(":");
+                if (!colon && !n.endsWith("*")) {
+                    n = n + "*";
+                }
+                sj.add(n);
+            }
+            stub = sj.toString();
+            writeSetting(main, profileProperties, "camel.jbang.stub", stub);
+            main.setStubPattern(stub);
+        }
+
         writeSetting(main, profileProperties, "camel.main.sourceLocationEnabled", "true");
         if (dev) {
             writeSetting(main, profileProperties, "camel.main.routesReloadEnabled", "true");
@@ -419,8 +443,9 @@ public class Run extends CamelCommand {
         }
 
         if (silentRun) {
+            main.setSilent(true);
             // enable stub in silent mode so we do not use real components
-            main.setStub(true);
+            main.setStubPattern("*");
             // do not run for very long in silent run
             main.addInitialProperty("camel.main.autoStartup", "false");
             main.addInitialProperty("camel.main.durationMaxSeconds", "1");
@@ -704,6 +729,7 @@ public class Run extends CamelCommand {
             jvmDebug = "true".equals(answer.getProperty("camel.jbang.jvmDebug", jvmDebug ? "true" : "false"));
             camelVersion = answer.getProperty("camel.jbang.camel-version", camelVersion);
             gav = answer.getProperty("camel.jbang.gav", gav);
+            stub = answer.getProperty("camel.jbang.stub", stub);
         }
         return answer;
     }
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java
index f3cf0e9b41d..97c7aaadcdc 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CatalogLoader.java
@@ -60,7 +60,8 @@ public final class CatalogLoader {
         try {
             main.setRepos(repos);
             // enable stub in silent mode so we do not use real components
-            main.setStub(true);
+            main.setSilent(true);
+            main.setStubPattern("*");
             main.start();
 
             // wrap downloaded catalog files in an isolated classloader
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index a6c4580f7d9..5555fae80cb 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -56,6 +56,7 @@ import org.apache.camel.main.download.DependencyDownloaderStrategy;
 import org.apache.camel.main.download.DependencyDownloaderUriFactoryResolver;
 import org.apache.camel.main.download.DownloadListener;
 import org.apache.camel.main.download.DownloadModelineParser;
+import org.apache.camel.main.download.KameletAutowiredLifecycleStrategy;
 import org.apache.camel.main.download.KameletMainInjector;
 import org.apache.camel.main.download.KnownDependenciesResolver;
 import org.apache.camel.main.download.KnownReposResolver;
@@ -72,6 +73,7 @@ import org.apache.camel.spi.DataFormatResolver;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.FactoryFinderResolver;
 import org.apache.camel.spi.LanguageResolver;
+import org.apache.camel.spi.LifecycleStrategy;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.spi.ResourceLoader;
 import org.apache.camel.spi.RoutesLoader;
@@ -107,7 +109,8 @@ public class KameletMain extends MainCommandLineSupport {
     private boolean verbose;
     private String mavenSettings;
     private String mavenSettingsSecurity;
-    private boolean stub;
+    private String stubPattern;
+    private boolean silent;
     private DownloadListener downloadListener;
     private DependencyDownloaderClassLoader classLoader;
 
@@ -212,8 +215,29 @@ public class KameletMain extends MainCommandLineSupport {
         this.fresh = fresh;
     }
 
-    public boolean isStub() {
-        return stub;
+    /**
+     * Whether to use stub endpoints instead of creating the actual endpoints. This allows to simulate using real
+     * components but run without them on the classpath.
+     *
+     * @param stubPattern endpoint pattern (Use * for all).
+     */
+    public void setStubPattern(String stubPattern) {
+        this.stubPattern = stubPattern;
+    }
+
+    public String getStubPattern() {
+        return stubPattern;
+    }
+
+    public boolean isSilent() {
+        return silent;
+    }
+
+    /**
+     * Whether to run in silent mode (used during export or resolving dependencies)
+     */
+    public void setSilent(boolean silent) {
+        this.silent = silent;
     }
 
     /**
@@ -240,14 +264,6 @@ public class KameletMain extends MainCommandLineSupport {
         return mavenSettingsSecurity;
     }
 
-    /**
-     * Whether to use stub endpoints instead of creating the actual endpoints. This allows to simulate using real
-     * components but run without them on the classpath.
-     */
-    public void setStub(boolean stub) {
-        this.stub = stub;
-    }
-
     public DownloadListener getDownloadListener() {
         return downloadListener;
     }
@@ -376,8 +392,8 @@ public class KameletMain extends MainCommandLineSupport {
             // in case we use circuit breakers
             CircuitBreakerDownloader.registerDownloadReifiers();
         }
-        if (stub) {
-            // turn off auto-wiring when running in stub mode
+        if (silent || "*".equals(stubPattern)) {
+            // turn off auto-wiring when running in silent mode (or stub = *)
             mainConfigurationProperties.setAutowiredEnabled(false);
             // and turn off fail fast as we stub components
             mainConfigurationProperties.setAutoConfigurationFailFast(false);
@@ -394,7 +410,8 @@ public class KameletMain extends MainCommandLineSupport {
         // annotation based dependency injection for camel/spring/quarkus annotations in DSLs and Java beans
         AnnotationDependencyInjection.initAnnotationBasedDependencyInjection(answer);
 
-        if (!stub) {
+        if (!silent) {
+            // silent should not include cli-connector
             // setup cli-connector if not already done
             if (answer.hasService(CliConnector.class) == null) {
                 CliConnectorFactory ccf = answer.getCamelContextExtension().getContextPlugin(CliConnectorFactory.class);
@@ -449,8 +466,8 @@ public class KameletMain extends MainCommandLineSupport {
             configure().httpServer().withEnabled(true);
             configure().httpServer().withHealthCheckEnabled(true);
         }
-        if (stub) {
-            // stub should not include http server
+        if (silent) {
+            // silent should not include http server
             configure().httpServer().withEnabled(false);
         }
 
@@ -506,7 +523,7 @@ public class KameletMain extends MainCommandLineSupport {
                 answer.getCamelContextExtension().setDefaultFactoryFinder(ff);
 
                 answer.getCamelContextExtension().addContextPlugin(ComponentResolver.class,
-                        new DependencyDownloaderComponentResolver(answer, stub));
+                        new DependencyDownloaderComponentResolver(answer, stubPattern, silent));
                 answer.getCamelContextExtension().addContextPlugin(UriFactoryResolver.class,
                         new DependencyDownloaderUriFactoryResolver(answer));
                 answer.getCamelContextExtension().addContextPlugin(DataFormatResolver.class,
@@ -516,7 +533,7 @@ public class KameletMain extends MainCommandLineSupport {
                 answer.getCamelContextExtension().addContextPlugin(ResourceLoader.class,
                         new DependencyDownloaderResourceLoader(answer));
             }
-            answer.setInjector(new KameletMainInjector(answer.getInjector(), stub));
+            answer.setInjector(new KameletMainInjector(answer.getInjector(), stubPattern, silent));
             if (download) {
                 answer.addService(new DependencyDownloaderKamelet(answer));
                 answer.getCamelContextExtension().getRegistry().bind(DownloadModelineParser.class.getSimpleName(),
@@ -566,6 +583,11 @@ public class KameletMain extends MainCommandLineSupport {
         super.autoconfigure(camelContext);
     }
 
+    @Override
+    protected LifecycleStrategy createLifecycleStrategy(CamelContext camelContext) {
+        return new KameletAutowiredLifecycleStrategy(camelContext, stubPattern, silent);
+    }
+
     protected ClassLoader createApplicationContextClassLoader() {
         if (classLoader == null) {
             // jars need to be added to dependency downloader classloader
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderComponentResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderComponentResolver.java
index 416eddbbab1..01d1bbe6749 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderComponentResolver.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloaderComponentResolver.java
@@ -40,17 +40,19 @@ import org.apache.camel.tooling.model.ComponentModel;
  */
 public final class DependencyDownloaderComponentResolver extends DefaultComponentResolver {
 
-    private static final String ACCEPTED_STUB_NAMES = "stub,bean,class,kamelet,rest,rest-api,platform-http,vertx-http";
+    private static final String ACCEPTED_STUB_NAMES = "stub,bean,class,log,kamelet,rest,rest-api,platform-http,vertx-http";
 
     private final CamelCatalog catalog = new DefaultCamelCatalog();
     private final CamelContext camelContext;
     private final DependencyDownloader downloader;
-    private final boolean stub;
+    private final String stubPattern;
+    private final boolean silent;
 
-    public DependencyDownloaderComponentResolver(CamelContext camelContext, boolean stub) {
+    public DependencyDownloaderComponentResolver(CamelContext camelContext, String stubPattern, boolean silent) {
         this.camelContext = camelContext;
         this.downloader = camelContext.hasService(DependencyDownloader.class);
-        this.stub = stub;
+        this.stubPattern = stubPattern;
+        this.silent = silent;
     }
 
     @Override
@@ -69,10 +71,11 @@ public final class DependencyDownloaderComponentResolver extends DefaultComponen
         } else {
             answer = super.resolveComponent("stub", context);
         }
-        if (stub && answer instanceof StubComponent) {
+        if ((silent || stubPattern != null) && answer instanceof StubComponent) {
             StubComponent sc = (StubComponent) answer;
             // enable shadow mode on stub component
             sc.setShadow(true);
+            sc.setShadowPattern(stubPattern);
         }
         if (answer instanceof PlatformHttpComponent) {
             // setup a default http server on port 8080 if not already done
@@ -81,7 +84,8 @@ public final class DependencyDownloaderComponentResolver extends DefaultComponen
                 // need to capture we use http-server
                 HttpServerConfigurationProperties config = new HttpServerConfigurationProperties(null);
                 CamelJBangSettingsHelper.writeSettings("camel.jbang.platform-http.port", String.valueOf(config.getPort()));
-                if (!stub) {
+                if (!silent) {
+                    // enable http server if not silent
                     MainHttpServerFactory factory = new DefaultMainHttpServerFactory();
                     Service httpServer = factory.newHttpServer(config);
                     try {
@@ -104,7 +108,7 @@ public final class DependencyDownloaderComponentResolver extends DefaultComponen
 
     private boolean accept(String name) {
         // kamelet component must not be stubbed
-        if (!stub) {
+        if (stubPattern == null) {
             return true;
         }
 
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletAutowiredLifecycleStrategy.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletAutowiredLifecycleStrategy.java
new file mode 100644
index 00000000000..de853e834c1
--- /dev/null
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletAutowiredLifecycleStrategy.java
@@ -0,0 +1,85 @@
+/*
+ * 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.download;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.main.MainAutowiredLifecycleStrategy;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.Language;
+import org.apache.camel.support.PatternHelper;
+
+public class KameletAutowiredLifecycleStrategy extends MainAutowiredLifecycleStrategy {
+
+    private final String stubPattern;
+    private final boolean silent;
+
+    public KameletAutowiredLifecycleStrategy(CamelContext camelContext, String stubPattern, boolean silent) {
+        super(camelContext);
+        this.stubPattern = stubPattern;
+        this.silent = silent;
+    }
+
+    @Override
+    protected boolean isEnabled(String name, Component component) {
+        boolean enabled = isEnabled(name);
+        if (enabled) {
+            return super.isEnabled(name, component);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    protected boolean isEnabled(String name, Language language) {
+        boolean enabled = isEnabled(name);
+        if (enabled) {
+            return super.isEnabled(name, language);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    protected boolean isEnabled(String name, DataFormat dataFormat) {
+        boolean enabled = isEnabled(name);
+        if (enabled) {
+            return super.isEnabled(name, dataFormat);
+        } else {
+            return false;
+        }
+    }
+
+    protected boolean isEnabled(String name) {
+        if (silent) {
+            return false;
+        }
+        if (stubPattern == null) {
+            return true;
+        } else if (stubPattern.equals("*")) {
+            return false;
+        } else {
+            // is the component stubbed, then it should not autowire
+            for (String n : stubPattern.split(",")) {
+                if (PatternHelper.matchPattern(n, stubPattern)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
index 83bd7ec1e19..7093a7a39a6 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
@@ -19,49 +19,47 @@ package org.apache.camel.main.download;
 import org.apache.camel.Component;
 import org.apache.camel.component.stub.StubComponent;
 import org.apache.camel.spi.Injector;
+import org.apache.camel.support.PatternHelper;
+import org.apache.camel.util.ObjectHelper;
 
 public class KameletMainInjector implements Injector {
 
     private static final String ACCEPTED_STUB_NAMES
-            = "StubComponent,BeanComponent,ClassComponent,KameletComponent,RestComponent,RestApiComponent,PlatformHttpComponent,VertxHttpComponent";
+            = "StubComponent,BeanComponent,ClassComponent,KameletComponent,RestComponent,RestApiComponent,PlatformHttpComponent,VertxHttpComponent,LogComponent";
 
     private final Injector delegate;
-    private final boolean stub;
+    private final String stubPattern;
+    private final boolean silent;
 
-    public KameletMainInjector(Injector delegate, boolean stub) {
+    public KameletMainInjector(Injector delegate, String stubPattern, boolean silent) {
         this.delegate = delegate;
-        this.stub = stub;
+        this.stubPattern = stubPattern;
+        this.silent = silent;
     }
 
     @Override
     public <T> T newInstance(Class<T> type) {
-        if (stub && Component.class.isAssignableFrom(type)) {
-            boolean accept = accept(type);
-            if (!accept) {
-                return (T) delegate.newInstance(StubComponent.class);
-            }
+        boolean accept = acceptComponent(type);
+        if (!accept) {
+            return (T) delegate.newInstance(StubComponent.class);
         }
         return delegate.newInstance(type);
     }
 
     @Override
     public <T> T newInstance(Class<T> type, String factoryMethod) {
-        if (stub && Component.class.isAssignableFrom(type)) {
-            boolean accept = accept(type);
-            if (!accept) {
-                return (T) delegate.newInstance(StubComponent.class);
-            }
+        boolean accept = acceptComponent(type);
+        if (!accept) {
+            return (T) delegate.newInstance(StubComponent.class);
         }
         return delegate.newInstance(type, factoryMethod);
     }
 
     @Override
     public <T> T newInstance(Class<T> type, boolean postProcessBean) {
-        if (stub && Component.class.isAssignableFrom(type)) {
-            boolean accept = accept(type);
-            if (!accept) {
-                return (T) delegate.newInstance(StubComponent.class);
-            }
+        boolean accept = acceptComponent(type);
+        if (!accept) {
+            return (T) delegate.newInstance(StubComponent.class);
         }
         return delegate.newInstance(type, postProcessBean);
     }
@@ -71,11 +69,31 @@ public class KameletMainInjector implements Injector {
         return delegate.supportsAutoWiring();
     }
 
-    private boolean accept(Class<?> type) {
-        if (!stub) {
-            return true;
+    private boolean acceptComponent(Class<?> type) {
+        boolean accept = true;
+        if (stubPattern != null && Component.class.isAssignableFrom(type)) {
+            accept = accept(type);
+            if (!accept && !"*".equals(stubPattern)) {
+                // grab component name via annotation trick!
+                org.apache.camel.spi.annotations.Component ann
+                        = ObjectHelper.getAnnotation(this, org.apache.camel.spi.annotations.Component.class);
+                if (ann != null) {
+                    boolean found = false;
+                    String name = ann.value();
+                    for (String n : name.split(",")) {
+                        if (PatternHelper.matchPattern(n, stubPattern)) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    accept = !found;
+                }
+            }
         }
+        return accept;
+    }
 
+    private boolean accept(Class<?> type) {
         String shortName = type.getSimpleName();
         // we are stubbing but need to accept the following
         return ACCEPTED_STUB_NAMES.contains(shortName);