This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.14.x by this push:
     new c249cf7be524 CAMEL-22507: camel-jbang - When using kamelets with 
dynamic EIPs such as toD then we need to resolve the kamelet name during export 
to ensure we can gather dependencies and kamelet spec files to be included in 
the export. (#19481)
c249cf7be524 is described below

commit c249cf7be52408a10a8856afd92d73368e82a9fd
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Oct 8 13:42:49 2025 +0200

    CAMEL-22507: camel-jbang - When using kamelets with dynamic EIPs such as 
toD then we need to resolve the kamelet name during export to ensure we can 
gather dependencies and kamelet spec files to be included in the export. 
(#19481)
---
 .../org/apache/camel/spi/ComponentResolver.java    |  3 +-
 ...solver.java => OptimisedComponentResolver.java} | 17 +++---
 .../camel/impl/engine/AbstractCamelContext.java    |  4 ++
 .../engine/DefaultOptimisedComponentResolver.java} | 33 +++++++-----
 .../camel/impl/engine/SimpleCamelContext.java      | 12 +++--
 .../java/org/apache/camel/processor/Enricher.java  |  1 +
 .../org/apache/camel/processor/PollEnricher.java   |  7 ++-
 .../camel/processor/SendDynamicProcessor.java      |  7 ++-
 .../org/apache/camel/support/ExchangeHelper.java   | 16 ++++++
 .../camel/dsl/jbang/core/commands/ExportTest.java  | 47 +++++++++++++++++
 .../src/test/resources/cheese-sink.kamelet.yaml    | 51 ++++++++++++++++++
 .../src/test/resources/toDroute.yaml               | 24 +++++++++
 .../java/org/apache/camel/main/KameletMain.java    |  4 ++
 .../KameletOptimisedComponentResolver.java         | 61 ++++++++++++++++++++++
 14 files changed, 255 insertions(+), 32 deletions(-)

diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
index 3d3f56ba529e..d836a74ff526 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
@@ -20,8 +20,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 
 /**
- * Represents a resolver of components from a URI to be able to auto-load them 
using some discovery mechanism like
- * {@link org.apache.camel.impl.DefaultComponentResolver}
+ * Represents a resolver of components from a URI to be able to autoload them 
using some discovery mechanism.
  */
 public interface ComponentResolver {
 
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java
similarity index 56%
copy from 
core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
copy to 
core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java
index 3d3f56ba529e..2e6504124199 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
+++ 
b/core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java
@@ -16,22 +16,19 @@
  */
 package org.apache.camel.spi;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 
 /**
- * Represents a resolver of components from a URI to be able to auto-load them 
using some discovery mechanism like
- * {@link org.apache.camel.impl.DefaultComponentResolver}
+ * A {@link Component} resolver that are used in EIPs with dynamic behavior 
such as toD, enrich and others.
  */
-public interface ComponentResolver {
+public interface OptimisedComponentResolver {
 
     /**
-     * Attempts to resolve the component for the given URI
+     * Resolves the given component
      *
-     * @param  name      the component name to resolve
-     * @param  context   the context to load the component if it can be 
resolved
-     * @return           the component which is added to the context or null 
if it cannot be resolved
-     * @throws Exception is thrown if the component could not be loaded
+     * @param  uri the endpoint uri
+     * @return     the component
      */
-    Component resolveComponent(String name, CamelContext context) throws 
Exception;
+    Component resolveComponent(String uri);
+
 }
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 bfc4026effe7..deda7b82a848 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
@@ -140,6 +140,7 @@ import org.apache.camel.spi.ModelToYAMLDumper;
 import org.apache.camel.spi.ModelineFactory;
 import org.apache.camel.spi.NodeIdFactory;
 import org.apache.camel.spi.NormalizedEndpointUri;
+import org.apache.camel.spi.OptimisedComponentResolver;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.PeriodTaskResolver;
@@ -361,6 +362,7 @@ public abstract class AbstractCamelContext extends 
BaseService
         camelContextExtension.addContextPlugin(FactoryFinderResolver.class, 
createFactoryFinderResolver());
         camelContextExtension.addContextPlugin(PackageScanClassResolver.class, 
createPackageScanClassResolver());
         
camelContextExtension.addContextPlugin(PackageScanResourceResolver.class, 
createPackageScanResourceResolver());
+        
camelContextExtension.addContextPlugin(OptimisedComponentResolver.class, 
createOptimisedComponentResolver());
         
camelContextExtension.addContextPlugin(VariableRepositoryFactory.class, 
createVariableRepositoryFactory());
         camelContextExtension.lazyAddContextPlugin(ModelineFactory.class, 
this::createModelineFactory);
         
camelContextExtension.lazyAddContextPlugin(ModelJAXBContextFactory.class, 
this::createModelJAXBContextFactory);
@@ -4448,6 +4450,8 @@ public abstract class AbstractCamelContext extends 
BaseService
 
     protected abstract TaskManagerRegistry createTaskManagerRegistry();
 
+    protected abstract OptimisedComponentResolver 
createOptimisedComponentResolver();
+
     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-api/src/main/java/org/apache/camel/spi/ComponentResolver.java 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java
similarity index 55%
copy from 
core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
copy to 
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java
index 3d3f56ba529e..fe9df3b86816 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java
@@ -14,24 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
+package org.apache.camel.impl.engine;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
+import org.apache.camel.spi.OptimisedComponentResolver;
+import org.apache.camel.support.ExchangeHelper;
 
 /**
- * Represents a resolver of components from a URI to be able to auto-load them 
using some discovery mechanism like
- * {@link org.apache.camel.impl.DefaultComponentResolver}
+ * Default {@link OptimisedComponentResolver}.
  */
-public interface ComponentResolver {
+public class DefaultOptimisedComponentResolver implements 
OptimisedComponentResolver {
 
-    /**
-     * Attempts to resolve the component for the given URI
-     *
-     * @param  name      the component name to resolve
-     * @param  context   the context to load the component if it can be 
resolved
-     * @return           the component which is added to the context or null 
if it cannot be resolved
-     * @throws Exception is thrown if the component could not be loaded
-     */
-    Component resolveComponent(String name, CamelContext context) throws 
Exception;
+    private final CamelContext camelContext;
+
+    public DefaultOptimisedComponentResolver(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public Component resolveComponent(String uri) {
+        String scheme = ExchangeHelper.resolveScheme(uri);
+        if (scheme != null) {
+            return camelContext.getComponent(scheme);
+        } else {
+            return null;
+        }
+    }
 }
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 0430cfdc7fe0..5502f3ab1476 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
@@ -72,6 +72,7 @@ import org.apache.camel.spi.ModelToYAMLDumper;
 import org.apache.camel.spi.ModelineFactory;
 import org.apache.camel.spi.NodeIdFactory;
 import org.apache.camel.spi.NormalizedEndpointUri;
+import org.apache.camel.spi.OptimisedComponentResolver;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.PeriodTaskResolver;
@@ -176,7 +177,7 @@ public class SimpleCamelContext extends 
AbstractCamelContext {
     @Override
     protected TypeConverter createTypeConverter() {
         return new DefaultTypeConverter(
-                getCamelContextReference(), 
PluginHelper.getPackageScanClassResolver(this), getInjector(),
+                getCamelContextReference(), 
PluginHelper.getPackageScanClassResolver(getCamelContextReference()), 
getInjector(),
                 isLoadTypeConverters(), isTypeConverterStatisticsEnabled());
     }
 
@@ -763,12 +764,17 @@ public class SimpleCamelContext extends 
AbstractCamelContext {
 
     @Override
     protected BackOffTimerFactory createBackOffTimerFactory() {
-        return new DefaultBackOffTimerFactory(this);
+        return new DefaultBackOffTimerFactory(getCamelContextReference());
     }
 
     @Override
     protected TaskManagerRegistry createTaskManagerRegistry() {
-        return new DefaultTaskManagerRegistry(this);
+        return new DefaultTaskManagerRegistry(getCamelContextReference());
+    }
+
+    @Override
+    protected OptimisedComponentResolver createOptimisedComponentResolver() {
+        return new 
DefaultOptimisedComponentResolver(getCamelContextReference());
     }
 
     @Override
diff --git 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java
 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java
index 33db45c6a7fa..0d69a6095b2e 100644
--- 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java
+++ 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java
@@ -312,6 +312,7 @@ public class Enricher extends BaseProcessorSupport 
implements IdAware, RouteIdAw
     @Override
     protected void doInit() throws Exception {
         headersMapFactory = 
camelContext.getCamelContextExtension().getHeadersMapFactory();
+        ServiceHelper.initService(processorExchangeFactory, 
aggregationStrategy, sendDynamicProcessor);
     }
 
     @Override
diff --git 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java
 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java
index 3d720587fc55..cec2a0733974 100644
--- 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java
+++ 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java
@@ -38,6 +38,7 @@ import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.ExceptionHandler;
 import org.apache.camel.spi.HeadersMapFactory;
 import org.apache.camel.spi.IdAware;
+import org.apache.camel.spi.OptimisedComponentResolver;
 import org.apache.camel.spi.PollDynamicAware;
 import org.apache.camel.spi.RouteIdAware;
 import org.apache.camel.support.BridgeExceptionHandlerToErrorHandler;
@@ -596,8 +597,10 @@ public class PollEnricher extends BaseProcessorSupport 
implements IdAware, Route
     @Override
     protected void doStart() throws Exception {
         // ensure the component is started
-        if (autoStartupComponents && scheme != null) {
-            camelContext.getComponent(scheme);
+        if (autoStartupComponents && scheme != null && uri != null) {
+            OptimisedComponentResolver resolver
+                    = 
camelContext.getCamelContextExtension().getContextPlugin(OptimisedComponentResolver.class);
+            resolver.resolveComponent(uri);
         }
 
         ServiceHelper.startService(consumerCache, aggregationStrategy, 
dynamicAware);
diff --git 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
index 1b2bd97733d0..1285ecf4af8e 100644
--- 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
+++ 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java
@@ -34,6 +34,7 @@ import org.apache.camel.spi.EndpointUtilizationStatistics;
 import org.apache.camel.spi.HeadersMapFactory;
 import org.apache.camel.spi.IdAware;
 import org.apache.camel.spi.NormalizedEndpointUri;
+import org.apache.camel.spi.OptimisedComponentResolver;
 import org.apache.camel.spi.ProducerCache;
 import org.apache.camel.spi.RouteIdAware;
 import org.apache.camel.spi.SendDynamicAware;
@@ -375,8 +376,10 @@ public class SendDynamicProcessor extends 
BaseProcessorSupport implements IdAwar
     @Override
     protected void doStart() throws Exception {
         // ensure the component is started
-        if (autoStartupComponents && scheme != null) {
-            camelContext.getComponent(scheme);
+        if (autoStartupComponents && scheme != null && uri != null) {
+            OptimisedComponentResolver resolver
+                    = 
camelContext.getCamelContextExtension().getContextPlugin(OptimisedComponentResolver.class);
+            resolver.resolveComponent(uri);
         }
 
         if (producerCache == null) {
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java 
b/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java
index c8fcc9e3f966..81c0f466b153 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java
@@ -918,6 +918,22 @@ public final class ExchangeHelper {
         return StringHelper.before(uri, ":");
     }
 
+    /**
+     * Resolve the context-path from the given endpoint uri
+     *
+     * @param  uri the endpoint uri
+     * @return     the context path, or <tt>null</tt> if not possible to 
resolve
+     */
+    public static String resolveContextPath(String uri) {
+        uri = StringHelper.before(uri, "?", uri);
+        if (uri.contains("://")) {
+            uri = StringHelper.after(uri, "://");
+        } else {
+            uri = StringHelper.after(uri, ":");
+        }
+        return uri;
+    }
+
     /**
      * @see #getCharsetName(Exchange, boolean)
      */
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
index 3e0b782c09cd..4ca3b0fd7c58 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
@@ -690,4 +690,51 @@ class ExportTest {
         }
     }
 
+    @ParameterizedTest
+    @MethodSource("runtimeProvider")
+    public void shouldExportToDWithCustomKamelet(RuntimeType rt) throws 
Exception {
+        LOG.info("shouldExportToDWithCustomKamelet {}", rt);
+        Export command = createCommand(rt,
+                new String[] { "src/test/resources/toDroute.yaml", 
"src/test/resources/cheese-sink.kamelet.yaml" },
+                "--gav=examples:route:1.0.0", "--dir=" + workingDir, 
"--quiet");
+        int exit = command.doCall();
+
+        Assertions.assertEquals(0, exit);
+        Model model = readMavenModel();
+        Assertions.assertEquals("examples", model.getGroupId());
+        Assertions.assertEquals("route", model.getArtifactId());
+        Assertions.assertEquals("1.0.0", model.getVersion());
+
+        if (rt == RuntimeType.main) {
+            Assertions.assertTrue(containsDependency(model.getDependencies(), 
"org.apache.camel", "camel-log", null));
+            Assertions.assertTrue(containsDependency(model.getDependencies(), 
"org.apache.camel", "camel-kamelet", null));
+            Assertions
+                    .assertFalse(
+                            containsDependency(model.getDependencies(), 
"org.apache.camel.kamelets", "camel-kamelets", null));
+        } else if (rt == RuntimeType.springBoot) {
+            Assertions.assertTrue(
+                    containsDependency(model.getDependencies(), 
"org.apache.camel.springboot", "camel-log-starter", null));
+            Assertions.assertTrue(
+                    containsDependency(model.getDependencies(), 
"org.apache.camel.springboot", "camel-kamelet-starter", null));
+            Assertions
+                    .assertFalse(
+                            containsDependency(model.getDependencies(), 
"org.apache.camel.kamelets", "camel-kamelets", null));
+        } else if (rt == RuntimeType.quarkus) {
+            Assertions.assertTrue(
+                    containsDependency(model.getDependencies(), 
"org.apache.camel.quarkus", "camel-quarkus-log", null));
+            Assertions.assertTrue(
+                    containsDependency(model.getDependencies(), 
"org.apache.camel.quarkus", "camel-quarkus-kamelet", null));
+            Assertions
+                    .assertFalse(
+                            containsDependency(model.getDependencies(), 
"org.apache.camel.kamelets", "camel-kamelets", null));
+        }
+
+        File f = 
workingDir.toPath().resolve("src/main/resources/kamelets/cheese-sink.kamelet.yaml").toFile();
+        Assertions.assertTrue(f.isFile());
+        Assertions.assertTrue(f.exists());
+        f = 
workingDir.toPath().resolve("src/main/resources/camel/toDroute.yaml").toFile();
+        Assertions.assertTrue(f.isFile());
+        Assertions.assertTrue(f.exists());
+    }
+
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml
new file mode 100644
index 000000000000..95d965509e68
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+
+apiVersion: camel.apache.org/v1
+kind: Kamelet
+metadata:
+  name: cheese-sink
+  labels:
+    camel.apache.org/kamelet.type: "sink"
+spec:
+  definition:
+    title: "Log Sink"
+    description: A sink that logs all data that it receives, useful for 
debugging purposes.
+    required:
+      - showHeaders
+    properties:
+      showHeaders:
+        title: Show Headers
+        description: Show the headers received
+        type: boolean
+      showStreams:
+        title: Show Streams
+        description: Show the stream bodies (they may not be available in 
following steps)
+        type: boolean
+        default: false
+  dependencies:
+    - "camel:kamelet"
+    - "camel:log"
+  template:
+    from:
+      uri: "kamelet:source"
+      steps:
+        - to:
+            uri: "log:info"
+            parameters:
+              showHeaders: "{{?showHeaders}}"
+              showStreams: "{{?showStreams}}"
\ No newline at end of file
diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml 
b/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml
new file mode 100644
index 000000000000..e0758cafe586
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+- from:
+    uri: timer:tick
+    steps:
+      - setBody:
+          constant: Hello Camel !!!
+      - toD:
+          uri: kamelet:cheese-sink
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 ec596295b328..1995317569fc 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
@@ -66,6 +66,7 @@ import 
org.apache.camel.main.download.JavaKnownImportsDownloader;
 import org.apache.camel.main.download.KameletAutowiredLifecycleStrategy;
 import org.apache.camel.main.download.KameletFallbackResourceResolver;
 import org.apache.camel.main.download.KameletMainInjector;
+import org.apache.camel.main.download.KameletOptimisedComponentResolver;
 import org.apache.camel.main.download.KnownDependenciesResolver;
 import org.apache.camel.main.download.KnownReposResolver;
 import org.apache.camel.main.download.MavenDependencyDownloader;
@@ -97,6 +98,7 @@ 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.OptimisedComponentResolver;
 import org.apache.camel.spi.PeriodTaskResolver;
 import org.apache.camel.spi.PeriodTaskScheduler;
 import org.apache.camel.spi.Registry;
@@ -669,6 +671,8 @@ public class KameletMain extends MainCommandLineSupport {
                     new DependencyDownloaderUriFactoryResolver(answer));
             
answer.getCamelContextExtension().addContextPlugin(ResourceLoader.class,
                     new DependencyDownloaderResourceLoader(answer, sourceDir));
+            
answer.getCamelContextExtension().addContextPlugin(OptimisedComponentResolver.class,
+                    new KameletOptimisedComponentResolver(answer));
 
             if (stubPattern != null) {
                 // need to replace autowire strategy with stub capable
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.java
 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.java
new file mode 100644
index 000000000000..7b2e6654530d
--- /dev/null
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.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.main.download;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.component.kamelet.KameletComponent;
+import org.apache.camel.impl.engine.DefaultOptimisedComponentResolver;
+import org.apache.camel.language.simple.SimpleLanguage;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.RouteTemplateHelper;
+
+/**
+ * Dynamic EIPs that are using kamelets should preload kamelets so we can 
resolve dependencies and what components these
+ * kamelets are using as well.
+ */
+public class KameletOptimisedComponentResolver extends 
DefaultOptimisedComponentResolver {
+
+    private final CamelContext camelContext;
+
+    public KameletOptimisedComponentResolver(CamelContext camelContext) {
+        super(camelContext);
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public Component resolveComponent(String uri) {
+        Component answer = super.resolveComponent(uri);
+        String scheme = ExchangeHelper.resolveScheme(uri);
+        // if a kamelet then we need to know the name of the kamelet spec in 
use
+        if ("kamelet".equals(scheme)) {
+            String name = ExchangeHelper.resolveContextPath(uri);
+            // must be a static name (so we can load the template and resolve 
nested dependencies)
+            if (!SimpleLanguage.hasSimpleFunction(name) && answer instanceof 
KameletComponent kc) {
+                // need to resolve dependencies from kamelet also
+                String loc = kc.getLocation();
+                DependencyDownloaderKamelet listener = 
camelContext.hasService(DependencyDownloaderKamelet.class);
+                try {
+                    
RouteTemplateHelper.loadRouteTemplateFromLocation(camelContext, listener, name, 
loc);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return answer;
+    }
+}

Reply via email to