You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2023/08/30 13:47:16 UTC

[camel-quarkus] branch main updated: Onboard Camel K Runtime

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

ppalaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 93d6053c7e Onboard Camel K Runtime
93d6053c7e is described below

commit 93d6053c7ea043ab1af7004ab0307726dc54a440
Author: Claudio Miranda <cl...@claudius.com.br>
AuthorDate: Mon Jul 24 13:24:42 2023 -0300

    Onboard Camel K Runtime
    
    https://github.com/apache/camel-quarkus/issues/4283
---
 catalog/pom.xml                                    |  14 +
 extensions/camel-k/deployment/pom.xml              | 154 +++++++
 .../camel/quarkus/k/deployment/RuntimeFeature.java |  29 ++
 .../quarkus/k/deployment/RuntimeProcessor.java     | 144 ++++++
 .../deployment/devmode/HotDeploymentProcessor.java | 115 +++++
 .../k/deployment/support/DeploymentSupport.java    |  61 +++
 .../camel/quarkus/k/deployment/LoaderTest.java     | 335 ++++++++++++++
 .../deployment/src/test/resources/MyRoutes.java    |  26 ++
 .../deployment/src/test/resources/routes.groovy    |  20 +
 .../deployment/src/test/resources/routes.js        |  19 +
 .../deployment/src/test/resources/routes.jsh       |  21 +
 .../deployment/src/test/resources/routes.kts       |  20 +
 .../deployment/src/test/resources/routes.xml       |  34 ++
 .../deployment/src/test/resources/routes.yaml      |  25 +
 {tooling => extensions/camel-k}/pom.xml            |  30 +-
 extensions/camel-k/runtime/pom.xml                 | 214 +++++++++
 .../quarkus/k/core/SourceDefinitionConfigurer.java | 114 +++++
 .../k/listener/SourcesConfigurerConfigurer.java    |  49 ++
 ...rg.apache.camel.quarkus.k.core.SourceDefinition |   2 +
 ...ache.camel.quarkus.k.listener.SourcesConfigurer |   2 +
 .../org/apache/camel/quarkus/k/core/Runtime.java   | 156 +++++++
 .../apache/camel/quarkus/k/core/RuntimeAware.java  |  24 +
 .../org/apache/camel/quarkus/k/core/Source.java    |  54 +++
 .../camel/quarkus/k/core/SourceDefinition.java     | 184 ++++++++
 .../apache/camel/quarkus/k/core/SourceType.java    |  24 +
 .../quarkus/k/listener/AbstractPhaseListener.java  |  39 ++
 .../quarkus/k/listener/ContextConfigurer.java      |  38 ++
 .../quarkus/k/listener/SourcesConfigurer.java      | 109 +++++
 .../camel/quarkus/k/runtime/Application.java       | 175 +++++++
 .../k/runtime/ApplicationConfigSourceProvider.java |  45 ++
 .../quarkus/k/runtime/ApplicationProducers.java    |  39 ++
 .../quarkus/k/runtime/ApplicationRecorder.java     |  48 ++
 .../apache/camel/quarkus/k/support/Constants.java  |  63 +++
 .../camel/quarkus/k/support/DelegatingRuntime.java |  80 ++++
 .../camel/quarkus/k/support/PropertiesSupport.java |  93 ++++
 .../camel/quarkus/k/support/RouteBuilders.java     |  73 +++
 .../camel/quarkus/k/support/RuntimeSupport.java    | 341 ++++++++++++++
 .../apache/camel/quarkus/k/support/Sources.java    | 243 ++++++++++
 .../camel/quarkus/k/support/SourcesSupport.java    | 187 ++++++++
 .../camel/quarkus/k/support/StringSupport.java     |  75 +++
 .../main/resources/META-INF/quarkus-extension.yaml |  33 ++
 ...rg.apache.camel.quarkus.k.core.Runtime$Listener |  19 +
 ...se.microprofile.config.spi.ConfigSourceProvider |  17 +
 .../org/apache/camel/quarkus/k/SourceTest.java     |  54 +++
 .../PropertiesFunctionsConfigurerTest.java         |  55 +++
 .../quarkus/k/listener/SourceConfigurerTest.java   | 143 ++++++
 .../camel/quarkus/k/support/NameCustomizer.java    |  45 ++
 .../quarkus/k/support/PropertiesSupportTest.java   |  94 ++++
 .../quarkus/k/support/RuntimeSupportTest.java      | 194 ++++++++
 .../org.apache.camel.quarkus.k/customizer/name     |  18 +
 .../configmaps/my-binary-cm/my-property.zip        | Bin 0 -> 186 bytes
 .../test/resources/configmaps/my-cm/my-property    |   1 +
 .../runtime/src/test/resources/my-cp-resource.txt  |   1 +
 .../src/test/resources/my-file-resource.txt        |   1 +
 .../test/resources/secrets/my-secret/my-property   |   1 +
 extensions/pom.xml                                 |   1 +
 integration-tests/camel-k-runtime/pom.xml          | 187 ++++++++
 .../org/apache/camel/quarkus/k/it/Application.java | 108 +++++
 .../camel/quarkus/k/it/RuntimeInspector.java       | 111 +++++
 .../camel/quarkus/k/it/yaml/BeanProducers.java     |  36 ++
 .../org/apache/camel/quarkus/k/it/yaml/MyBean.java |  46 ++
 .../camel/quarkus/k/it/yaml/MyProcessor.java       |  28 ++
 .../src/main/resources/application.properties      |  21 +
 .../quarkus/k/it/RuntimeCustomizerFallbackIT.java  |  23 +
 .../k/it/RuntimeCustomizerFallbackTest.java        |  58 +++
 .../camel/quarkus/k/it/RuntimeCustomizerIT.java    |  23 +
 .../camel/quarkus/k/it/RuntimeCustomizerTest.java  |  58 +++
 .../org/apache/camel/quarkus/k/it/RuntimeIT.java   |  23 +
 .../org/apache/camel/quarkus/k/it/RuntimeTest.java |  60 +++
 .../camel/quarkus/k/it/RuntimeWithXmlIT.java       |  23 +
 .../camel/quarkus/k/it/RuntimeWithXmlTest.java     |  74 +++
 .../camel/quarkus/k/it/RuntimeWithYamlIT.java      |  23 +
 .../camel/quarkus/k/it/RuntimeWithYamlTest.java    |  77 ++++
 .../apache/camel/quarkus/k/it/TestCustomizer.java  |  50 ++
 .../org.apache.camel.quarkus.k/customizer/test     |  18 +
 .../src/test/resources/conf.d/001/conf.properties  |  17 +
 .../src/test/resources/conf.d/002/conf.properties  |  18 +
 .../src/test/resources/conf.d/003/flat-property    |   1 +
 .../src/test/resources/conf.properties             |  21 +
 .../camel-k-runtime/src/test/resources/rests.xml   |  27 ++
 .../src/test/resources/routes-with-beans.yaml      |  31 ++
 .../src/test/resources/routes-with-expression.xml  |  28 ++
 .../camel-k-runtime/src/test/resources/routes.xml  |  25 +
 integration-tests/pom.xml                          |   1 +
 pom.xml                                            |   4 +
 poms/bom-test/pom.xml                              |  10 +
 poms/bom/pom.xml                                   |  54 ++-
 poms/bom/src/main/generated/flattened-full-pom.xml |  79 ++--
 .../src/main/generated/flattened-reduced-pom.xml   |  24 +-
 .../generated/flattened-reduced-verbose-pom.xml    |  24 +-
 tooling/camel-k-catalog-model/pom.xml              |  96 ++++
 .../camel/quarkus/k/catalog/model/Artifact.java    |  59 +++
 .../quarkus/k/catalog/model/CamelArtifact.java     |  82 ++++
 .../quarkus/k/catalog/model/CamelCapability.java   |  47 ++
 .../camel/quarkus/k/catalog/model/CamelLoader.java |  62 +++
 .../camel/quarkus/k/catalog/model/CamelScheme.java |  66 +++
 .../k/catalog/model/CamelScopedArtifact.java       |  50 ++
 .../catalog/model/CatalogComponentDefinition.java  |  80 ++++
 .../catalog/model/CatalogDataFormatDefinition.java |  58 +++
 .../quarkus/k/catalog/model/CatalogDefinition.java |  47 ++
 .../k/catalog/model/CatalogLanguageDefinition.java |  58 +++
 .../k/catalog/model/CatalogOtherDefinition.java    |  49 ++
 .../quarkus/k/catalog/model/CatalogSupport.java    |  51 ++
 .../quarkus/k/catalog/model/k8s/ObjectMeta.java    |  38 ++
 .../quarkus/k/catalog/model/k8s/TypeMeta.java      |  37 ++
 .../k/catalog/model/k8s/crd/CamelCatalog.java      |  44 ++
 .../k/catalog/model/k8s/crd/CamelCatalogSpec.java  |  56 +++
 .../k/catalog/model/k8s/crd/RuntimeSpec.java       |  63 +++
 tooling/camel-k-maven-plugin/pom.xml               | 266 +++++++++++
 .../it/generate-catalog-with-exclusions/pom.xml    | 110 +++++
 .../generate-catalog-with-exclusions/verify.groovy |  40 ++
 .../src/it/generate-catalog/pom.xml                | 104 +++++
 .../src/it/generate-catalog/verify.groovy          | 121 +++++
 .../src/it/generate-dependencies/pom.xml           | 107 +++++
 .../src/it/generate-dependencies/verify.groovy     |  46 ++
 .../src/it/generate-rest-dsl-from-v2/document.json |  46 ++
 .../src/it/generate-rest-dsl-from-v2/pom.xml       | 102 ++++
 .../src/it/generate-rest-dsl-from-v2/verify.groovy |  27 ++
 .../src/it/generate-rest-dsl-from-v3/document.yaml | 128 ++++++
 .../src/it/generate-rest-dsl-from-v3/pom.xml       | 102 ++++
 .../src/it/generate-rest-dsl-from-v3/verify.groovy |  29 ++
 .../k/tooling/maven/GenerateCatalogMojo.java       | 512 +++++++++++++++++++++
 .../tooling/maven/GenerateDependencyListMojo.java  | 132 ++++++
 .../quarkus/k/tooling/maven/GenerateRestXML.java   | 102 ++++
 .../quarkus/k/tooling/maven/GenerateSupport.java   |  38 ++
 .../k/tooling/maven/support/MavenSupport.java      | 120 +++++
 .../src/main/resources/app.properties              |  18 +
 .../src/main/resources/catalog-license.txt         |  17 +
 tooling/pom.xml                                    |   2 +
 tooling/scripts/test-categories.yaml               |   1 +
 130 files changed, 8752 insertions(+), 67 deletions(-)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 412865d5db..aeff08564c 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -695,6 +695,19 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-camel-k</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-cassandraql</artifactId>
@@ -4313,6 +4326,7 @@
                         <configuration>
                             <skipArtifactIdBases>
                                 <skipArtifactIdBase>http-common</skipArtifactIdBase>
+                                <skipArtifactIdBase>camel-k</skipArtifactIdBase>
                                 <skipArtifactIdBase>support-.*</skipArtifactIdBase>
                                 <skipArtifactIdBase>integration-tests?-support-.*</skipArtifactIdBase>
                             </skipArtifactIdBases>
diff --git a/extensions/camel-k/deployment/pom.xml b/extensions/camel-k/deployment/pom.xml
new file mode 100644
index 0000000000..3aabc908b1
--- /dev/null
+++ b/extensions/camel-k/deployment/pom.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-camel-k-parent</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-camel-k-deployment</artifactId>
+    <name>Camel Quarkus :: Camel K :: Deployment</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-camel-k</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-kubernetes-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5-internal</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-groovy-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-java-joor-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-js-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-jsh-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-kotlin-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-yaml-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-xml-io-dsl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-jackson</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-log</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jsonb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jsonb</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>io.quarkus</groupId>
+                            <artifactId>quarkus-extension-processor</artifactId>
+                            <version>${quarkus.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeFeature.java b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeFeature.java
new file mode 100644
index 0000000000..be92d4ebf4
--- /dev/null
+++ b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeFeature.java
@@ -0,0 +1,29 @@
+/*
+ * 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.quarkus.k.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+public class RuntimeFeature {
+    private static final String FEATURE = "camel-k-runtime";
+
+    @BuildStep
+    FeatureBuildItem feature() {
+        return new FeatureBuildItem(FEATURE);
+    }
+}
diff --git a/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeProcessor.java b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeProcessor.java
new file mode 100644
index 0000000000..02c674f4ef
--- /dev/null
+++ b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/RuntimeProcessor.java
@@ -0,0 +1,144 @@
+/*
+ * 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.quarkus.k.deployment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.stream.Collectors;
+
+import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.BeanContainerBuildItem;
+import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.Consume;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
+import org.apache.camel.builder.RouteBuilderLifecycleStrategy;
+import org.apache.camel.quarkus.core.deployment.main.spi.CamelMainBuildItem;
+import org.apache.camel.quarkus.core.deployment.main.spi.CamelMainListenerBuildItem;
+import org.apache.camel.quarkus.core.deployment.main.spi.CamelRoutesCollectorBuildItem;
+import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeTaskBuildItem;
+import org.apache.camel.quarkus.core.deployment.spi.CamelServiceDestination;
+import org.apache.camel.quarkus.core.deployment.spi.CamelServicePatternBuildItem;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.runtime.ApplicationProducers;
+import org.apache.camel.quarkus.k.runtime.ApplicationRecorder;
+import org.apache.camel.quarkus.k.support.Constants;
+import org.apache.camel.quarkus.k.support.RuntimeSupport;
+import org.apache.camel.spi.CamelContextCustomizer;
+import org.apache.camel.spi.StreamCachingStrategy;
+import org.jboss.jandex.IndexView;
+
+import static org.apache.camel.quarkus.k.deployment.support.DeploymentSupport.getAllKnownImplementors;
+import static org.apache.camel.quarkus.k.deployment.support.DeploymentSupport.reflectiveClassBuildItem;
+import static org.apache.camel.quarkus.k.deployment.support.DeploymentSupport.stream;
+
+public class RuntimeProcessor {
+
+    @Record(ExecutionTime.STATIC_INIT)
+    @BuildStep
+    CamelMainListenerBuildItem mainListener(ApplicationRecorder recorder) {
+        List<Runtime.Listener> listeners = new ArrayList<>();
+        ServiceLoader.load(Runtime.Listener.class).forEach(listeners::add);
+
+        return new CamelMainListenerBuildItem(recorder.createMainListener(listeners));
+    }
+
+    @Record(ExecutionTime.STATIC_INIT)
+    @BuildStep
+    CamelRoutesCollectorBuildItem routesCollector(ApplicationRecorder recorder) {
+        return new CamelRoutesCollectorBuildItem(recorder.createRoutesCollector());
+    }
+
+    @Record(ExecutionTime.RUNTIME_INIT)
+    @BuildStep
+    @Consume(SyntheticBeansRuntimeInitBuildItem.class)
+    CamelRuntimeTaskBuildItem registerRuntime(
+            ApplicationRecorder recorder,
+            CamelMainBuildItem camelMain,
+            BeanContainerBuildItem beanContainer) {
+
+        recorder.publishRuntime(camelMain.getInstance(), beanContainer.getValue());
+        recorder.version(RuntimeSupport.getRuntimeVersion());
+
+        return new CamelRuntimeTaskBuildItem("camel-k-runtime");
+    }
+
+    @BuildStep
+    List<AdditionalBeanBuildItem> unremovableBeans() {
+        return List.of(
+                AdditionalBeanBuildItem.unremovableOf(ApplicationProducers.class));
+    }
+
+    @BuildStep
+    List<CamelServicePatternBuildItem> servicePatterns() {
+        return List.of(
+                new CamelServicePatternBuildItem(
+                        CamelServiceDestination.REGISTRY,
+                        true,
+                        Constants.CONTEXT_CUSTOMIZER_RESOURCE_PATH + "/*"),
+                new CamelServicePatternBuildItem(
+                        CamelServiceDestination.DISCOVERY,
+                        true,
+                        Constants.SOURCE_LOADER_INTERCEPTOR_RESOURCE_PATH + "/*"));
+    }
+
+    @BuildStep
+    List<ReflectiveClassBuildItem> registerClasses(CombinedIndexBuildItem index) {
+        return List.of(
+                ReflectiveClassBuildItem.builder(SourceDefinition.class).methods().fields(false).build(),
+                reflectiveClassBuildItem(getAllKnownImplementors(index.getIndex(), CamelContextCustomizer.class)),
+                reflectiveClassBuildItem(getAllKnownImplementors(index.getIndex(), RouteBuilderLifecycleStrategy.class)));
+    }
+
+    @BuildStep
+    List<ServiceProviderBuildItem> registerServices(CombinedIndexBuildItem combinedIndexBuildItem) {
+        final IndexView view = combinedIndexBuildItem.getIndex();
+        final String serviceType = "org.apache.camel.quarkus.k.core.Runtime$Listener";
+        return stream(getAllKnownImplementors(view, serviceType))
+                .map(i -> new ServiceProviderBuildItem(serviceType, i.name().toString()))
+                .collect(Collectors.toList());
+    }
+
+    @BuildStep
+    void registerStreamCachingClasses(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
+            CombinedIndexBuildItem combinedIndex) {
+
+        final IndexView view = combinedIndex.getIndex();
+
+        getAllKnownImplementors(view, StreamCachingStrategy.class)
+                .forEach(i -> reflectiveClass.produce(reflectiveClassBuildItem(i)));
+
+        getAllKnownImplementors(view, StreamCachingStrategy.Statistics.class)
+                .forEach(i -> reflectiveClass.produce(reflectiveClassBuildItem(i)));
+
+        getAllKnownImplementors(view, StreamCachingStrategy.SpoolRule.class)
+                .forEach(i -> reflectiveClass.produce(reflectiveClassBuildItem(i)));
+
+        reflectiveClass.produce(
+                ReflectiveClassBuildItem.builder("StreamCachingStrategy.SpoolRule.class")
+                        .methods()
+                        .fields()
+                        .build());
+    }
+}
diff --git a/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/devmode/HotDeploymentProcessor.java b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/devmode/HotDeploymentProcessor.java
new file mode 100644
index 0000000000..8777938ca5
--- /dev/null
+++ b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/devmode/HotDeploymentProcessor.java
@@ -0,0 +1,115 @@
+/*
+ * 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.quarkus.k.deployment.devmode;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
+import org.apache.camel.quarkus.k.support.Constants;
+import org.apache.camel.util.StringHelper;
+import org.apache.commons.io.FilenameUtils;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HotDeploymentProcessor {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(HotDeploymentProcessor.class);
+
+    @BuildStep
+    List<HotDeploymentWatchedFileBuildItem> routes() {
+        final Config config = ConfigProvider.getConfig();
+        final Optional<String> value = config.getOptionalValue(Constants.PROPERTY_CAMEL_K_ROUTES, String.class);
+
+        List<HotDeploymentWatchedFileBuildItem> items = new ArrayList<>();
+
+        if (value.isPresent()) {
+            for (String source : value.get().split(",", -1)) {
+                String path = StringHelper.after(source, ":");
+                if (path == null) {
+                    path = source;
+                }
+
+                Path p = Paths.get(path);
+                if (Files.exists(p)) {
+                    LOGGER.info("Register source for hot deployment: {}", p.toAbsolutePath());
+                    items.add(new HotDeploymentWatchedFileBuildItem(p.toAbsolutePath().toString()));
+                }
+            }
+        }
+
+        return items;
+    }
+
+    @BuildStep
+    List<HotDeploymentWatchedFileBuildItem> conf() {
+        final Config config = ConfigProvider.getConfig();
+        final Optional<String> conf = config.getOptionalValue(Constants.PROPERTY_CAMEL_K_CONF, String.class);
+        final Optional<String> confd = config.getOptionalValue(Constants.PROPERTY_CAMEL_K_CONF_D, String.class);
+
+        List<HotDeploymentWatchedFileBuildItem> items = new ArrayList<>();
+
+        if (conf.isPresent()) {
+            LOGGER.info("Register conf for hot deployment: {}", conf.get());
+            items.add(new HotDeploymentWatchedFileBuildItem(conf.get()));
+        }
+
+        if (confd.isPresent()) {
+            FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    Objects.requireNonNull(file);
+                    Objects.requireNonNull(attrs);
+
+                    String path = file.toFile().getAbsolutePath();
+                    String ext = FilenameUtils.getExtension(path);
+
+                    if (Objects.equals("properties", ext)) {
+                        LOGGER.info("Register conf for hot deployment: {}", path);
+                        items.add(new HotDeploymentWatchedFileBuildItem(path));
+                    }
+
+                    return FileVisitResult.CONTINUE;
+                }
+            };
+
+            Path root = Paths.get(confd.get());
+            if (Files.exists(root)) {
+                try {
+                    Files.walkFileTree(root, visitor);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        return items;
+    }
+}
diff --git a/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/support/DeploymentSupport.java b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/support/DeploymentSupport.java
new file mode 100644
index 0000000000..9f9e744fdb
--- /dev/null
+++ b/extensions/camel-k/deployment/src/main/java/org/apache/camel/quarkus/k/deployment/support/DeploymentSupport.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.quarkus.k.deployment.support;
+
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.IndexView;
+
+public final class DeploymentSupport {
+
+    private DeploymentSupport() {
+    }
+
+    public static Iterable<ClassInfo> getAllKnownImplementors(IndexView view, String name) {
+        return view.getAllKnownImplementors(DotName.createSimple(name));
+    }
+
+    public static Iterable<ClassInfo> getAllKnownImplementors(IndexView view, Class<?> type) {
+        return getAllKnownImplementors(view, type.getName());
+    }
+
+    public static ReflectiveClassBuildItem reflectiveClassBuildItem(ClassInfo... classInfos) {
+        return classInfos.length == 1
+                ? ReflectiveClassBuildItem.builder(classInfos[0].name().toString()).methods().fields(false).build()
+                : ReflectiveClassBuildItem.builder(Stream.of(classInfos)
+                        .map(ClassInfo::name)
+                        .map(DotName::toString)
+                        .toArray(String[]::new))
+                        .methods().fields(false).build();
+    }
+
+    public static ReflectiveClassBuildItem reflectiveClassBuildItem(Iterable<ClassInfo> classInfos) {
+        return ReflectiveClassBuildItem.builder(stream(classInfos)
+                .map(ClassInfo::name)
+                .map(DotName::toString)
+                .toArray(String[]::new))
+                .methods().fields(false).build();
+    }
+
+    public static <T> Stream<T> stream(Iterable<T> iterable) {
+        return StreamSupport.stream(iterable.spliterator(), false);
+    }
+}
diff --git a/extensions/camel-k/deployment/src/test/java/org/apache/camel/quarkus/k/deployment/LoaderTest.java b/extensions/camel-k/deployment/src/test/java/org/apache/camel/quarkus/k/deployment/LoaderTest.java
new file mode 100644
index 0000000000..5d398f4f54
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/java/org/apache/camel/quarkus/k/deployment/LoaderTest.java
@@ -0,0 +1,335 @@
+/*
+ * 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.quarkus.k.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.ServiceLoader;
+
+import io.quarkus.test.QuarkusUnitTest;
+import io.restassured.RestAssured;
+import io.restassured.path.json.JsonPath;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.json.Json;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObject;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.k.listener.ContextConfigurer;
+import org.apache.camel.quarkus.k.listener.SourcesConfigurer;
+import org.apache.camel.spi.RoutesLoader;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.IOHelper;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LoaderTest {
+    @RegisterExtension
+    public static final QuarkusUnitTest test = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+                    .addClasses(Application.class, LoaderSupport.class)
+                    .addAsResource("MyRoutes.java")
+                    .addAsResource("routes.groovy")
+                    .addAsResource("routes.js")
+                    .addAsResource("routes.jsh")
+                    .addAsResource("routes.kts")
+                    .addAsResource("routes.xml")
+                    .addAsResource("routes.yaml"))
+            .overrideConfigKey("quarkus.camel.routes-discovery.enabled", "false");
+
+    @Test
+    public void testServices() {
+        JsonPath p = RestAssured.given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/loader/services")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("services", String.class)).contains(
+                ContextConfigurer.class.getName(),
+                SourcesConfigurer.class.getName());
+    }
+
+    @Test
+    public void testLoadGroovyRoutes() throws IOException {
+        String code;
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.groovy")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/groovy/MyRoute")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("groovy");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://groovy", "log://groovy");
+    }
+
+    @Test
+    public void testLoadJavaRoutes() throws IOException {
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/MyRoutes.java")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/java/MyRoutes")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("java");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://java", "log://java");
+    }
+
+    @Test
+    public void testLoadJavascriptRoutes() throws IOException {
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.js")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/js/MyRoute")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("js");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://js", "log://js");
+    }
+
+    @Test
+    public void testLoadJshRoutes() throws IOException {
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.jsh")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/jsh/routes")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("jsh");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://jsh", "log://jsh");
+    }
+
+    @Test
+    public void testLoadKotlinRoutes() throws IOException {
+
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.kts")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/kts/MyRoute")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("kotlin");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://kotlin", "log://kotlin");
+    }
+
+    @Test
+    public void testLoadXmlRoutes() throws IOException {
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.xml")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/xml/MyRoute")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("xml");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://xml", "log://xml");
+    }
+
+    @Test
+    public void testLoadYamlRoutes() throws IOException {
+        String code;
+
+        try (InputStream is = LoaderTest.class.getResourceAsStream("/routes.yaml")) {
+            code = IOHelper.loadText(is);
+        }
+
+        JsonPath p = RestAssured.given()
+                .contentType(MediaType.TEXT_PLAIN)
+                .accept(MediaType.APPLICATION_JSON)
+                .body(code)
+                .post("/camel-k/loader/load-routes/yaml/MyRoute")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("components", String.class)).contains("direct", "log");
+        assertThat(p.getList("routes", String.class)).contains("yaml");
+        assertThat(p.getList("endpoints", String.class)).contains("direct://yaml", "log://yaml");
+    }
+
+    @Path("/camel-k/loader")
+    @ApplicationScoped
+    public static class Application {
+
+        @Inject
+        CamelContext context;
+
+        // k-core
+        @GET
+        @Path("/services")
+        @Produces(MediaType.APPLICATION_JSON)
+        public JsonObject getServices() {
+            JsonArrayBuilder builder = Json.createArrayBuilder();
+
+            ServiceLoader.load(Runtime.Listener.class).forEach(listener -> {
+                builder.add(listener.getClass().getName());
+            });
+
+            return Json.createObjectBuilder()
+                    .add("services", builder)
+                    .build();
+        }
+
+        @POST
+        @Path("/load-routes/{loaderName}/{name}")
+        @Consumes(MediaType.TEXT_PLAIN)
+        @Produces(MediaType.APPLICATION_JSON)
+        public JsonObject loadRoutes(@PathParam("loaderName") String loaderName, @PathParam("name") String name, byte[] code)
+                throws Exception {
+            return LoaderSupport.inspectSource(context, name + "." + loaderName, code);
+        }
+    }
+
+    static final class LoaderSupport {
+        private LoaderSupport() {
+        }
+
+        public static JsonObject inspectSource(CamelContext context, String location, byte[] code) throws Exception {
+            final Runtime runtime = Runtime.on(context);
+            final ExtendedCamelContext ecc = runtime.getExtendedCamelContext();
+            final RoutesLoader loader = PluginHelper.getRoutesLoader(ecc);
+            final Collection<RoutesBuilder> builders = loader.findRoutesBuilders(ResourceHelper.fromBytes(location, code));
+
+            for (RoutesBuilder builder : builders) {
+                runtime.addRoutes(builder);
+            }
+
+            return Json.createObjectBuilder()
+                    .add("components", extractComponents(context))
+                    .add("routes", extractRoutes(context))
+                    .add("endpoints", extractEndpoints(context))
+                    .build();
+        }
+
+        public static JsonObject inspectSource(CamelContext context, String location, String code) throws Exception {
+            return inspectSource(context, location, code.getBytes(StandardCharsets.UTF_8));
+        }
+
+        public static JsonArrayBuilder extractComponents(CamelContext context) {
+            JsonArrayBuilder answer = Json.createArrayBuilder();
+            context.getComponentNames().forEach(answer::add);
+
+            return answer;
+        }
+
+        public static JsonArrayBuilder extractRoutes(CamelContext context) {
+            JsonArrayBuilder answer = Json.createArrayBuilder();
+            context.getRoutes().forEach(r -> answer.add(r.getId()));
+
+            return answer;
+        }
+
+        public static JsonArrayBuilder extractEndpoints(CamelContext context) {
+            JsonArrayBuilder answer = Json.createArrayBuilder();
+            context.getEndpoints().forEach(e -> answer.add(e.getEndpointUri()));
+
+            return answer;
+        }
+    }
+
+}
diff --git a/extensions/camel-k/deployment/src/test/resources/MyRoutes.java b/extensions/camel-k/deployment/src/test/resources/MyRoutes.java
new file mode 100644
index 0000000000..d305e3e2d5
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/MyRoutes.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyRoutes extends RouteBuilder {
+    @Override
+    public void configure() throws Exception {
+        from("direct:java")
+            .routeId("java")
+            .to("log:java");
+    }
+}
\ No newline at end of file
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.groovy b/extensions/camel-k/deployment/src/test/resources/routes.groovy
new file mode 100644
index 0000000000..a96deb2378
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.groovy
@@ -0,0 +1,20 @@
+/*
+ * 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('direct:groovy')
+    .routeId('groovy')
+    .to('log:groovy')
\ No newline at end of file
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.js b/extensions/camel-k/deployment/src/test/resources/routes.js
new file mode 100644
index 0000000000..414fe0a798
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.js
@@ -0,0 +1,19 @@
+/*
+ * 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('direct:js')
+    .routeId('js')
+    .to('log:js')
\ No newline at end of file
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.jsh b/extensions/camel-k/deployment/src/test/resources/routes.jsh
new file mode 100644
index 0000000000..c47a78f30f
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.jsh
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+
+builder.from("direct:jsh")
+    .routeId("jsh")
+    .to("log:jsh");
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.kts b/extensions/camel-k/deployment/src/test/resources/routes.kts
new file mode 100644
index 0000000000..fba70eee0b
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.kts
@@ -0,0 +1,20 @@
+/*
+ * 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("direct:kotlin")
+    .routeId("kotlin")
+    .to("log:kotlin")
\ No newline at end of file
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.xml b/extensions/camel-k/deployment/src/test/resources/routes.xml
new file mode 100644
index 0000000000..2bb35d9d4d
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="http://camel.apache.org/schema/spring"
+        xsi:schemaLocation="
+            http://camel.apache.org/schema/spring
+            http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+    <route id="xml">
+        <from uri="direct:xml"/>
+        <marshal>
+            <json/>
+        </marshal>
+        <to uri="log:xml"/>
+    </route>
+
+</routes>
\ No newline at end of file
diff --git a/extensions/camel-k/deployment/src/test/resources/routes.yaml b/extensions/camel-k/deployment/src/test/resources/routes.yaml
new file mode 100644
index 0000000000..be866f3300
--- /dev/null
+++ b/extensions/camel-k/deployment/src/test/resources/routes.yaml
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+- route:
+    id: yaml
+    from:
+      uri: 'direct:yaml'
+      steps:
+        - marshal:
+            json: {}
+        - to: 'log:yaml'
diff --git a/tooling/pom.xml b/extensions/camel-k/pom.xml
similarity index 60%
copy from tooling/pom.xml
copy to extensions/camel-k/pom.xml
index 748afb2770..ac3fcb2213 100644
--- a/tooling/pom.xml
+++ b/extensions/camel-k/pom.xml
@@ -19,37 +19,19 @@
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
-
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus</artifactId>
+        <artifactId>camel-quarkus-extensions</artifactId>
         <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>camel-quarkus-tooling</artifactId>
+    <artifactId>camel-quarkus-camel-k-parent</artifactId>
+    <name>Camel Quarkus :: Camel K</name>
     <packaging>pom</packaging>
 
-    <name>Camel Quarkus :: Tooling</name>
-    <description>Camel Quarkus Tooling Parent POM</description>
-
     <modules>
-        <module>maven-plugin</module>
-        <module>perf-regression</module>
-        <module>test-list</module>
+        <module>deployment</module>
+        <module>runtime</module>
     </modules>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>com.google.code.gson</groupId>
-                <artifactId>gson</artifactId>
-                <version>${gson.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.freemarker</groupId>
-                <artifactId>freemarker</artifactId>
-                <version>${freemarker.version}</version>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
 </project>
diff --git a/extensions/camel-k/runtime/pom.xml b/extensions/camel-k/runtime/pom.xml
new file mode 100644
index 0000000000..06c5018bd8
--- /dev/null
+++ b/extensions/camel-k/runtime/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-camel-k-parent</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-camel-k</artifactId>
+    <name>Camel Quarkus :: Camel K :: Runtime</name>
+    <description>Camel runtime specialization for Camel K</description>
+
+    <properties>
+        <camel.quarkus.jvmSince>3.3.0</camel.quarkus.jvmSince>
+        <camel.quarkus.nativeSince>3.3.0</camel.quarkus.nativeSince>
+        <quarkus.metadata.unlisted>true</quarkus.metadata.unlisted>
+        <camel-quarkus.update-extension-doc-page.skip>true</camel-quarkus.update-extension-doc-page.skip>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-arc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-engine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-languages</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-endpointdsl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-util</artifactId>
+        </dependency>
+        <!-- The camel-quarkus-kubernetes is required for the kubernetes property resolver -->
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-kubernetes</artifactId>
+        </dependency>
+
+
+        <!-- Tests  -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5-internal</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-base-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.jandex</groupId>
+                <artifactId>jandex-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>make-index</id>
+                        <goals>
+                            <goal>jandex</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-package-maven-plugin</artifactId>
+                <version>${camel.version}</version>
+                <executions>
+                    <execution>
+                        <id>generate-configurer</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>generate-configurer</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                            <goal>add-resource</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/generated/java</source>
+                            </sources>
+                            <resources>
+                                <resource>
+                                    <directory>src/generated/resources</directory>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-extension-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>io.quarkus</groupId>
+                            <artifactId>quarkus-extension-processor</artifactId>
+                            <version>${quarkus.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <environmentVariables>
+                        <CAMEL_K_RESOURCE_001>my env content</CAMEL_K_RESOURCE_001>
+                        <MY_ENV_RESOURCE_TXT>env:CAMEL_K_RESOURCE_001</MY_ENV_RESOURCE_TXT>
+                        <CAMEL_K_RESOURCE_002>H4sIAFlah1wAA8utVEjOzy0oSi0uTk1RSM0rA3LzSlLzSrgAUbkzGRoAAAA=</CAMEL_K_RESOURCE_002>
+                        <MY_COMPRESSED_ENV_RESOURCE_TXT>env:CAMEL_K_RESOURCE_002?compression=true</MY_COMPRESSED_ENV_RESOURCE_TXT>
+                    </environmentVariables>
+                    <systemPropertyVariables>
+                        <root>${project.basedir}</root>
+                        <camel.k.mount-path.configmaps>${project.basedir}/src/test/resources/configmaps</camel.k.mount-path.configmaps>
+                        <camel.k.mount-path.secrets>${project.basedir}/src/test/resources/secrets</camel.k.mount-path.secrets>
+                        <camel.kubernetes-config.client-enabled>false</camel.kubernetes-config.client-enabled>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>full</id>
+            <activation>
+                <property>
+                    <name>!quickly</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.camel.quarkus</groupId>
+                        <artifactId>camel-quarkus-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>update-extension-doc-page</id>
+                                <goals>
+                                    <goal>update-extension-doc-page</goal>
+                                </goals>
+                                <phase>process-classes</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/core/SourceDefinitionConfigurer.java b/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/core/SourceDefinitionConfigurer.java
new file mode 100644
index 0000000000..be4f0d7a7f
--- /dev/null
+++ b/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/core/SourceDefinitionConfigurer.java
@@ -0,0 +1,114 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.quarkus.k.core;
+
+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.quarkus.k.core.SourceDefinition;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class SourceDefinitionConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        org.apache.camel.quarkus.k.core.SourceDefinition target = (org.apache.camel.quarkus.k.core.SourceDefinition) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "compressed":
+        case "Compressed": target.setCompressed(property(camelContext, boolean.class, value)); return true;
+        case "content":
+        case "Content": target.setContent(property(camelContext, byte[].class, value)); return true;
+        case "id":
+        case "Id": target.setId(property(camelContext, java.lang.String.class, value)); return true;
+        case "interceptors":
+        case "Interceptors": target.setInterceptors(property(camelContext, java.util.List.class, value)); return true;
+        case "language":
+        case "Language": target.setLanguage(property(camelContext, java.lang.String.class, value)); return true;
+        case "loader":
+        case "Loader": target.setLoader(property(camelContext, java.lang.String.class, value)); return true;
+        case "location":
+        case "Location": target.setLocation(property(camelContext, java.lang.String.class, value)); return true;
+        case "name":
+        case "Name": target.setName(property(camelContext, java.lang.String.class, value)); return true;
+        case "propertynames":
+        case "PropertyNames": target.setPropertyNames(property(camelContext, java.util.List.class, value)); return true;
+        case "type":
+        case "Type": target.setType(property(camelContext, org.apache.camel.quarkus.k.core.SourceType.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "compressed":
+        case "Compressed": return boolean.class;
+        case "content":
+        case "Content": return byte[].class;
+        case "id":
+        case "Id": return java.lang.String.class;
+        case "interceptors":
+        case "Interceptors": return java.util.List.class;
+        case "language":
+        case "Language": return java.lang.String.class;
+        case "loader":
+        case "Loader": return java.lang.String.class;
+        case "location":
+        case "Location": return java.lang.String.class;
+        case "name":
+        case "Name": return java.lang.String.class;
+        case "propertynames":
+        case "PropertyNames": return java.util.List.class;
+        case "type":
+        case "Type": return org.apache.camel.quarkus.k.core.SourceType.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.quarkus.k.core.SourceDefinition target = (org.apache.camel.quarkus.k.core.SourceDefinition) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "compressed":
+        case "Compressed": return target.isCompressed();
+        case "content":
+        case "Content": return target.getContent();
+        case "id":
+        case "Id": return target.getId();
+        case "interceptors":
+        case "Interceptors": return target.getInterceptors();
+        case "language":
+        case "Language": return target.getLanguage();
+        case "loader":
+        case "Loader": return target.getLoader();
+        case "location":
+        case "Location": return target.getLocation();
+        case "name":
+        case "Name": return target.getName();
+        case "propertynames":
+        case "PropertyNames": return target.getPropertyNames();
+        case "type":
+        case "Type": return target.getType();
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getCollectionValueType(Object target, String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "interceptors":
+        case "Interceptors": return java.lang.String.class;
+        case "propertynames":
+        case "PropertyNames": return java.lang.String.class;
+        default: return null;
+        }
+    }
+}
+
diff --git a/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/listener/SourcesConfigurerConfigurer.java b/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/listener/SourcesConfigurerConfigurer.java
new file mode 100644
index 0000000000..d0586e63f8
--- /dev/null
+++ b/extensions/camel-k/runtime/src/generated/java/org/apache/camel/quarkus/k/listener/SourcesConfigurerConfigurer.java
@@ -0,0 +1,49 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.quarkus.k.listener;
+
+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.quarkus.k.listener.SourcesConfigurer;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class SourcesConfigurerConfigurer extends org.apache.camel.support.component.PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        org.apache.camel.quarkus.k.listener.SourcesConfigurer target = (org.apache.camel.quarkus.k.listener.SourcesConfigurer) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "sources":
+        case "Sources": target.setSources(property(camelContext, org.apache.camel.quarkus.k.core.SourceDefinition[].class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "sources":
+        case "Sources": return org.apache.camel.quarkus.k.core.SourceDefinition[].class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.quarkus.k.listener.SourcesConfigurer target = (org.apache.camel.quarkus.k.listener.SourcesConfigurer) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "sources":
+        case "Sources": return target.getSources();
+        default: return null;
+        }
+    }
+}
+
diff --git a/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.core.SourceDefinition b/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.core.SourceDefinition
new file mode 100644
index 0000000000..92383b0230
--- /dev/null
+++ b/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.core.SourceDefinition
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.quarkus.k.core.SourceDefinitionConfigurer
diff --git a/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.listener.SourcesConfigurer b/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.listener.SourcesConfigurer
new file mode 100644
index 0000000000..6a1ffed062
--- /dev/null
+++ b/extensions/camel-k/runtime/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.quarkus.k.listener.SourcesConfigurer
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.quarkus.k.listener.SourcesConfigurerConfigurer
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Runtime.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Runtime.java
new file mode 100644
index 0000000000..f67b227753
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Runtime.java
@@ -0,0 +1,156 @@
+/*
+ * 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.quarkus.k.core;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.Ordered;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.HasCamelContext;
+import org.apache.camel.spi.Registry;
+
+import static org.apache.camel.util.CollectionHelper.mapOf;
+
+public interface Runtime extends HasCamelContext, AutoCloseable {
+    /**
+     * Returns the camel context adapting it to the specialized type.
+     *
+     * @see    HasCamelContext#getCamelContext()
+     *
+     * @return the extended camel context.
+     */
+    default ExtendedCamelContext getExtendedCamelContext() {
+        return getCamelContext().getCamelContextExtension();
+    }
+
+    /**
+     * Returns the registry associated to this runtime.
+     */
+    default Registry getRegistry() {
+        return getCamelContext().getRegistry();
+    }
+
+    /**
+     * Sets a special list of properties that take precedence and will use first, if a property exist.
+     *
+     * @see              org.apache.camel.spi.PropertiesComponent#setOverrideProperties(Properties)
+     * @param properties the properties to set
+     */
+    default void setProperties(Properties properties) {
+        getCamelContext().getPropertiesComponent().setOverrideProperties(properties);
+    }
+
+    /**
+     * Sets a special list of properties that take precedence and will use first, if a property exist.
+     *
+     * @see              org.apache.camel.spi.PropertiesComponent#setOverrideProperties(Properties)
+     * @param properties the properties to set
+     */
+    default void setProperties(Map<String, String> properties) {
+        Properties p = new Properties();
+        p.putAll(properties);
+
+        setProperties(p);
+    }
+
+    /**
+     * Sets a special list of properties that take precedence and will use first, if a property exist.
+     *
+     * @see           org.apache.camel.spi.PropertiesComponent#setOverrideProperties(Properties)
+     * @param key     the mapping's key
+     * @param value   the mapping's value
+     * @param entries containing the keys and values from which the map is populated
+     *
+     */
+    default void setProperties(String key, String value, String... entries) {
+        setProperties(
+                mapOf(HashMap::new, key, value, entries));
+    }
+
+    /**
+     * Sets a special list of properties that take precedence and will use first, if a property exist.
+     *
+     * @see           org.apache.camel.spi.PropertiesComponent#setOverrideProperties(Properties)
+     * @param builder the builder which will create the routes
+     */
+    default void addRoutes(RoutesBuilder builder) {
+        try {
+            getCamelContext().addRoutes(builder);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+    /**
+     * Lifecycle method used to stops the entire integration.
+     */
+    default void stop() throws Exception {
+        // Stopping the Camel context in default config is enough to tear down the integration
+        getCamelContext().stop();
+    }
+
+    @Override
+    default void close() throws Exception {
+        stop();
+    }
+
+    enum Phase {
+        Initializing,
+        ConfigureProperties,
+        ConfigureContext,
+        ConfigureRoutes,
+        Starting,
+        Started,
+        Stopping,
+        Stopped
+    }
+
+    @FunctionalInterface
+    interface Listener extends Ordered {
+        boolean accept(Phase phase, Runtime runtime);
+
+        @Override
+        default int getOrder() {
+            return Ordered.LOWEST;
+        }
+    }
+
+    /**
+     * Helper to create a simple runtime from a given Camel Context.
+     *
+     * @param  camelContext the camel context
+     * @return              the runtime
+     */
+    static Runtime on(CamelContext camelContext) {
+        return () -> camelContext;
+    }
+
+    /**
+     * Helper to create a simple runtime from a given Camel Context provider.
+     *
+     * @param  provider the camel context provider
+     * @return          the runtime
+     */
+    static Runtime on(HasCamelContext provider) {
+        return provider::getCamelContext;
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/RuntimeAware.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/RuntimeAware.java
new file mode 100644
index 0000000000..a6df6d2d4e
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/RuntimeAware.java
@@ -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.
+ */
+package org.apache.camel.quarkus.k.core;
+
+public interface RuntimeAware {
+
+    void setRuntime(Runtime runtime);
+
+    Runtime getRuntime();
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Source.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Source.java
new file mode 100644
index 0000000000..afbe41235b
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/Source.java
@@ -0,0 +1,54 @@
+/*
+ * 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.quarkus.k.core;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.HasId;
+
+public interface Source extends HasId {
+    String getLocation();
+
+    String getName();
+
+    String getLanguage();
+
+    SourceType getType();
+
+    Optional<String> getLoader();
+
+    List<String> getInterceptors();
+
+    List<String> getPropertyNames();
+
+    InputStream resolveAsInputStream(CamelContext ctx);
+
+    default Reader resolveAsReader(CamelContext ctx) {
+        return resolveAsReader(ctx, StandardCharsets.UTF_8);
+    }
+
+    default Reader resolveAsReader(CamelContext ctx, Charset charset) {
+        return new InputStreamReader(resolveAsInputStream(ctx), charset);
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceDefinition.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceDefinition.java
new file mode 100644
index 0000000000..45ba6cef9c
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceDefinition.java
@@ -0,0 +1,184 @@
+/*
+ * 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.quarkus.k.core;
+
+import java.util.List;
+
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.IdAware;
+
+@Configurer
+public class SourceDefinition implements IdAware {
+    private String id;
+    private String name;
+    private String language;
+    private String loader;
+    private List<String> interceptors;
+    // Default as source type
+    private SourceType type = SourceType.source;
+    private List<String> propertyNames;
+    private String location;
+    private byte[] content;
+    private boolean compressed;
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * Sets the id
+     */
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * The name of the source.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getLanguage() {
+        return language;
+    }
+
+    /**
+     * The language use to define the source.
+     */
+    public void setLanguage(String language) {
+        this.language = language;
+    }
+
+    public String getLoader() {
+        return loader;
+    }
+
+    /**
+     * The {@link SourceLoader} that should be used to load the content of the source.
+     */
+    public void setLoader(String loader) {
+        this.loader = loader;
+    }
+
+    public List<String> getInterceptors() {
+        return interceptors;
+    }
+
+    /**
+     * The {@link org.apache.camel.quarkus.SourceLoader.Interceptor} that should be applied.
+     */
+    public void setInterceptors(List<String> interceptors) {
+        this.interceptors = interceptors;
+    }
+
+    public SourceType getType() {
+        return type;
+    }
+
+    /**
+     * The {@link SourceType} of the source.
+     */
+    public void setType(SourceType type) {
+        this.type = type;
+    }
+
+    public List<String> getPropertyNames() {
+        return propertyNames;
+    }
+
+    /**
+     * The list of properties names the source requires (used only for templates).
+     */
+    public void setPropertyNames(List<String> propertyNames) {
+        this.propertyNames = propertyNames;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    /**
+     * The location of the source.
+     */
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    public byte[] getContent() {
+        return content;
+    }
+
+    /**
+     * The content of the source.
+     */
+    public void setContent(byte[] content) {
+        this.content = content;
+    }
+
+    public boolean isCompressed() {
+        return compressed;
+    }
+
+    /**
+     * If the content of the source is compressed.
+     */
+    public void setCompressed(boolean compressed) {
+        this.compressed = compressed;
+    }
+
+    @Override
+    public String toString() {
+        String answer = "";
+
+        if (name != null) {
+            answer += "name='" + name + "', ";
+        }
+        if (language != null) {
+            answer += "language='" + language + "', ";
+        }
+        if (loader != null) {
+            answer += "loader='" + loader + "', ";
+        }
+        if (interceptors != null) {
+            answer += "interceptors='" + interceptors + "', ";
+        }
+        if (type != null) {
+            answer += "type='" + type + "', ";
+        }
+        if (propertyNames != null) {
+            answer += "propertyNames='" + propertyNames + "', ";
+        }
+        if (location != null) {
+            answer += "location='" + location + "', ";
+        }
+        if (compressed) {
+            answer += "compressed='true', ";
+        }
+        if (content != null) {
+            answer += "<...>";
+        }
+
+        return "SourceDefinition{" + answer + '}';
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceType.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceType.java
new file mode 100644
index 0000000000..da4e053ad4
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/core/SourceType.java
@@ -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.
+ */
+package org.apache.camel.quarkus.k.core;
+
+public enum SourceType {
+    // Order matters. We want the sources to be loaded following this enum order.
+    errorHandler,
+    template,
+    source
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/AbstractPhaseListener.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/AbstractPhaseListener.java
new file mode 100644
index 0000000000..f303ba3aad
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/AbstractPhaseListener.java
@@ -0,0 +1,39 @@
+/*
+ * 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.quarkus.k.listener;
+
+import org.apache.camel.quarkus.k.core.Runtime;
+
+public abstract class AbstractPhaseListener implements Runtime.Listener {
+    private final Runtime.Phase phase;
+
+    protected AbstractPhaseListener(Runtime.Phase phase) {
+        this.phase = phase;
+    }
+
+    @Override
+    public boolean accept(Runtime.Phase phase, Runtime runtime) {
+        boolean run = this.phase == phase;
+        if (run) {
+            accept(runtime);
+        }
+
+        return run;
+    }
+
+    protected abstract void accept(Runtime runtime);
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/ContextConfigurer.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/ContextConfigurer.java
new file mode 100644
index 0000000000..7c1f965c48
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/ContextConfigurer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.quarkus.k.listener;
+
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.k.support.RuntimeSupport;
+
+public class ContextConfigurer extends AbstractPhaseListener {
+
+    public ContextConfigurer() {
+        super(Runtime.Phase.ConfigureContext);
+    }
+
+    @Override
+    protected void accept(Runtime runtime) {
+        //
+        // Programmatically configure the camel context.
+        //
+        // This is useful to configure services such as the ClusterService,
+        // RouteController, etc
+        //
+        RuntimeSupport.configureContextCustomizers(runtime.getCamelContext());
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/SourcesConfigurer.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/SourcesConfigurer.java
new file mode 100644
index 0000000000..dd221e1451
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/listener/SourcesConfigurer.java
@@ -0,0 +1,109 @@
+/*
+ * 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.quarkus.k.listener;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.core.SourceType;
+import org.apache.camel.quarkus.k.support.Constants;
+import org.apache.camel.quarkus.k.support.PropertiesSupport;
+import org.apache.camel.quarkus.k.support.SourcesSupport;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.util.ObjectHelper;
+
+@Configurer
+public class SourcesConfigurer extends AbstractPhaseListener {
+
+    public static final String CAMEL_K_PREFIX = "camel.k.";
+    public static final String CAMEL_K_SOURCES_PREFIX = "camel.k.sources[";
+
+    private SourceDefinition[] sources;
+
+    public SourcesConfigurer() {
+        super(Runtime.Phase.ConfigureRoutes);
+    }
+
+    public SourceDefinition[] getSources() {
+        return sources;
+    }
+
+    public void setSources(SourceDefinition[] sources) {
+        this.sources = sources;
+    }
+
+    @Override
+    protected void accept(Runtime runtime) {
+        //
+        // load routes from env var for backward compatibility
+        //
+        String routes = System.getProperty(Constants.PROPERTY_CAMEL_K_ROUTES);
+        if (ObjectHelper.isEmpty(routes)) {
+            routes = System.getenv(Constants.ENV_CAMEL_K_ROUTES);
+        }
+
+        if (ObjectHelper.isNotEmpty(routes)) {
+            SourcesSupport.loadSources(runtime, routes.split(","));
+        }
+
+        //
+        // load routes from properties
+        //
+        // In order not to load any unwanted property, the filer remove any
+        // property that can't be bound to this configurer.
+        //
+        PropertiesSupport.bindProperties(
+                runtime.getCamelContext(),
+                this,
+                k -> k.startsWith(CAMEL_K_SOURCES_PREFIX),
+                CAMEL_K_PREFIX);
+
+        checkUniqueErrorHandler();
+        sortSources();
+
+        if (ObjectHelper.isNotEmpty(this.getSources())) {
+            SourcesSupport.loadSources(runtime, this.getSources());
+        }
+    }
+
+    private void checkUniqueErrorHandler() {
+        checkUniqueErrorHandler(this.sources);
+    }
+
+    static void checkUniqueErrorHandler(SourceDefinition[] sources) {
+        long errorHandlers = sources == null ? 0
+                : Arrays.stream(sources).filter(s -> s.getType() == SourceType.errorHandler).count();
+        if (errorHandlers > 1) {
+            throw new IllegalArgumentException("Expected only one error handler source type, got " + errorHandlers);
+        }
+    }
+
+    private void sortSources() {
+        sortSources(this.getSources());
+    }
+
+    static void sortSources(SourceDefinition[] sources) {
+        if (sources == null) {
+            return;
+        }
+        // We must ensure the source order as defined in SourceType enum
+        Arrays.sort(sources, Comparator.comparingInt(a -> a.getType().ordinal()));
+    }
+
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/Application.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/Application.java
new file mode 100644
index 0000000000..95bcf6636c
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/Application.java
@@ -0,0 +1,175 @@
+/*
+ * 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.quarkus.k.runtime;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.arc.ArcContainer;
+import io.quarkus.arc.InstanceHandle;
+import io.quarkus.runtime.Quarkus;
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.main.BaseMainSupport;
+import org.apache.camel.main.MainListener;
+import org.apache.camel.main.RoutesCollector;
+import org.apache.camel.spi.Resource;
+
+public final class Application {
+
+    private Application() {
+    }
+
+    /**
+     * The camel-k runtime impl based on camel-quarkus
+     */
+    public static class Runtime implements org.apache.camel.quarkus.k.core.Runtime {
+        private final BaseMainSupport main;
+        private final AtomicBoolean stopped;
+
+        public Runtime(BaseMainSupport main) {
+            this.main = main;
+            this.main.configure().setAutoConfigurationLogSummary(false);
+            this.stopped = new AtomicBoolean();
+        }
+
+        @Override
+        public CamelContext getCamelContext() {
+            return main.getCamelContext();
+        }
+
+        @Override
+        public void addRoutes(RoutesBuilder builder) {
+            main.configure().addRoutesBuilder(builder);
+        }
+
+        @Override
+        public void setProperties(Properties properties) {
+            main.setOverrideProperties(properties);
+        }
+
+        @Override
+        public void stop() throws Exception {
+            if (!this.stopped.compareAndExchange(false, true)) {
+                Quarkus.asyncExit();
+            }
+        }
+    }
+
+    /**
+     * Adapts main events to camel-k runtime lifecycle
+     */
+    public static class ListenerAdapter implements MainListener {
+        private final org.apache.camel.quarkus.k.core.Runtime.Listener[] listeners;
+
+        public ListenerAdapter(List<org.apache.camel.quarkus.k.core.Runtime.Listener> listeners) {
+            this.listeners = listeners.stream()
+                    .sorted(Comparator.comparingInt(org.apache.camel.quarkus.k.core.Runtime.Listener::getOrder))
+                    .toArray(org.apache.camel.quarkus.k.core.Runtime.Listener[]::new);
+        }
+
+        @Override
+        public void beforeInitialize(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.Initializing);
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.ConfigureProperties);
+        }
+
+        @Override
+        public void beforeConfigure(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.ConfigureRoutes);
+        }
+
+        @Override
+        public void afterConfigure(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.ConfigureContext);
+        }
+
+        @Override
+        public void beforeStart(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.Starting);
+        }
+
+        @Override
+        public void afterStart(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.Started);
+        }
+
+        @Override
+        public void beforeStop(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.Stopping);
+        }
+
+        @Override
+        public void afterStop(BaseMainSupport main) {
+            invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase.Stopped);
+        }
+
+        private void invokeListeners(org.apache.camel.quarkus.k.core.Runtime.Phase phase) {
+            org.apache.camel.quarkus.k.core.Runtime runtime = instance(org.apache.camel.quarkus.k.core.Runtime.class)
+                    .orElseThrow(() -> new IllegalStateException("Unable to fine a Runtime instance"));
+
+            for (int i = 0; i < listeners.length; i++) {
+                listeners[i].accept(phase, runtime);
+            }
+        }
+    }
+
+    /**
+     * Since routes are programmatically loaded, create a no-hop collector
+     */
+    public static class NoRoutesCollector implements RoutesCollector {
+        @Override
+        public Collection<RoutesBuilder> collectRoutesFromDirectory(CamelContext camelContext, String excludePattern,
+                String includePattern) {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public Collection<Resource> findRouteResourcesFromDirectory(CamelContext camelContext, String excludePattern,
+                String includePattern) {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<RoutesBuilder> collectRoutesFromRegistry(CamelContext camelContext, String excludePattern,
+                String includePattern) {
+            return Collections.emptyList();
+        }
+    }
+
+    // *********************************
+    //
+    // Helpers
+    //
+    // *********************************
+
+    public static Optional<ArcContainer> container() {
+        return Optional.of(Arc.container());
+    }
+
+    public static <T> Optional<T> instance(Class<T> type) {
+        return container()
+                .map(container -> container.instance(type))
+                .map(InstanceHandle::get);
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationConfigSourceProvider.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationConfigSourceProvider.java
new file mode 100644
index 0000000000..f0fb7f90f6
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationConfigSourceProvider.java
@@ -0,0 +1,45 @@
+/*
+ * 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.quarkus.k.runtime;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.smallrye.config.PropertiesConfigSource;
+import org.apache.camel.component.kubernetes.properties.ConfigMapPropertiesFunction;
+import org.apache.camel.quarkus.k.support.RuntimeSupport;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
+
+public class ApplicationConfigSourceProvider implements ConfigSourceProvider {
+
+    @Override
+    public Iterable<ConfigSource> getConfigSources(ClassLoader forClassLoader) {
+        final Map<String, String> sysProperties = new HashMap<>();
+        // explicit disable looking up configmap and secret using the KubernetesClient
+        sysProperties.put(ConfigMapPropertiesFunction.CLIENT_ENABLED, "false");
+
+        final Map<String, String> appProperties = RuntimeSupport.loadApplicationProperties();
+        final Map<String, String> usrProperties = RuntimeSupport.loadUserProperties();
+
+        return List.of(
+                new PropertiesConfigSource(sysProperties, "camel-k-sys", ConfigSource.DEFAULT_ORDINAL + 1000),
+                new PropertiesConfigSource(appProperties, "camel-k-app", ConfigSource.DEFAULT_ORDINAL),
+                new PropertiesConfigSource(usrProperties, "camel-k-usr", ConfigSource.DEFAULT_ORDINAL + 1));
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationProducers.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationProducers.java
new file mode 100644
index 0000000000..9e0509d550
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationProducers.java
@@ -0,0 +1,39 @@
+/*
+ * 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.quarkus.k.runtime;
+
+import io.quarkus.arc.Unremovable;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import jakarta.inject.Singleton;
+import org.apache.camel.quarkus.k.core.Runtime;
+
+@ApplicationScoped
+public class ApplicationProducers {
+    private volatile Runtime runtime;
+
+    public void setRuntime(Runtime runtime) {
+        this.runtime = runtime;
+    }
+
+    @Unremovable
+    @Singleton
+    @Produces
+    Runtime runtime() {
+        return this.runtime;
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationRecorder.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationRecorder.java
new file mode 100644
index 0000000000..5e06ec9bd6
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/runtime/ApplicationRecorder.java
@@ -0,0 +1,48 @@
+/*
+ * 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.quarkus.k.runtime;
+
+import java.util.List;
+
+import io.quarkus.arc.runtime.BeanContainer;
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import org.apache.camel.main.MainListener;
+import org.apache.camel.main.RoutesCollector;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.main.CamelMain;
+import org.slf4j.LoggerFactory;
+
+@Recorder
+public class ApplicationRecorder {
+
+    public void version(String version) {
+        LoggerFactory.getLogger(Runtime.class).info("Apache Camel K Runtime {}", version);
+    }
+
+    public RuntimeValue<MainListener> createMainListener(List<Runtime.Listener> listeners) {
+        return new RuntimeValue<>(new Application.ListenerAdapter(listeners));
+    }
+
+    public void publishRuntime(RuntimeValue<CamelMain> main, BeanContainer container) {
+        container.beanInstance(ApplicationProducers.class).setRuntime(new Application.Runtime(main.getValue()));
+    }
+
+    public RuntimeValue<RoutesCollector> createRoutesCollector() {
+        return new RuntimeValue<>(new Application.NoRoutesCollector());
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Constants.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Constants.java
new file mode 100644
index 0000000000..3979ba7af6
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Constants.java
@@ -0,0 +1,63 @@
+/*
+ * 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.quarkus.k.support;
+
+public final class Constants {
+    public static final String ENV_CAMEL_K_ROUTES = "CAMEL_K_ROUTES";
+    public static final String PROPERTY_CAMEL_K_ROUTES = "camel.k.routes";
+
+    public static final String ENV_CAMEL_K_CONF = "CAMEL_K_CONF";
+    public static final String PROPERTY_CAMEL_K_CONF = "camel.k.conf";
+
+    public static final String ENV_CAMEL_K_CONF_D = "CAMEL_K_CONF_D";
+    public static final String PROPERTY_CAMEL_K_CONF_D = "camel.k.conf.d";
+
+    public static final String ENV_CAMEL_K_CUSTOMIZERS = "CAMEL_K_CUSTOMIZERS";
+    public static final String PROPERTY_CAMEL_K_CUSTOMIZER = "camel.k.customizer";
+
+    public static final String ENV_CAMEL_K_MOUNT_PATH_CONFIGMAPS = "CAMEL_K_MOUNT_PATH_CONFIGMAPS";
+    public static final String PROPERTY_CAMEL_K_MOUNT_PATH_CONFIGMAPS = "camel.k.mount-path.configmaps";
+
+    public static final String ENV_CAMEL_K_MOUNT_PATH_SECRETS = "CAMEL_K_MOUNT_PATH_SECRETS";
+    public static final String PROPERTY_CAMEL_K_MOUNT_PATH_SECRETS = "camel.k.mount-path.secrets";
+
+    public static final String SCHEME_REF = "ref";
+    public static final String SCHEME_PREFIX_REF = SCHEME_REF + ":";
+    public static final String SCHEME_CLASS = "class";
+    public static final String SCHEME_PREFIX_CLASS = SCHEME_CLASS + ":";
+    public static final String SCHEME_CLASSPATH = "classpath";
+    public static final String SCHEME_PREFIX_CLASSPATH = SCHEME_CLASSPATH + ":";
+    public static final String SCHEME_FILE = "file";
+    public static final String SCHEME_PREFIX_FILE = SCHEME_FILE + ":";
+
+    public static final String LOGGING_LEVEL_PREFIX = "logging.level.";
+    public static final String SOURCE_LOADER_INTERCEPTOR_RESOURCE_PATH = "META-INF/services/org.apache.camel.quarkus.k/loader/interceptor/";
+    public static final String CONTEXT_CUSTOMIZER_RESOURCE_PATH = "META-INF/services/org.apache.camel.quarkus.k/customizer/";
+
+    public static final String ENABLE_CUSTOMIZER_PATTERN = "(camel\\.k\\.)?customizer\\.([\\w][\\w-]*)\\.enabled";
+
+    public static final String PROPERTY_PREFIX_REST_COMPONENT_PROPERTY = "camel.rest.componentProperty.";
+    public static final String PROPERTY_PREFIX_REST_ENDPOINT_PROPERTY = "camel.rest.endpointProperty.";
+
+    public static final String CUSTOMIZER_PREFIX = "camel.k.customizer.";
+    public static final String CUSTOMIZER_PREFIX_FALLBACK = "customizer.";
+    public static final String LOADER_INTERCEPTOR_PREFIX = "camel.k.loader.interceptor.";
+    public static final String LOADER_INTERCEPTOR_PREFIX_FALLBACK = "loader.interceptor.";
+
+    private Constants() {
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/DelegatingRuntime.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/DelegatingRuntime.java
new file mode 100644
index 0000000000..2cc6221758
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/DelegatingRuntime.java
@@ -0,0 +1,80 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.spi.Registry;
+
+public class DelegatingRuntime implements Runtime {
+
+    private final Runtime runtime;
+
+    public DelegatingRuntime(Runtime runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    public ExtendedCamelContext getExtendedCamelContext() {
+        return runtime.getExtendedCamelContext();
+    }
+
+    @Override
+    public Registry getRegistry() {
+        return runtime.getRegistry();
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+        runtime.setProperties(properties);
+    }
+
+    @Override
+    public void setProperties(Map<String, String> properties) {
+        runtime.setProperties(properties);
+    }
+
+    @Override
+    public void setProperties(String key, String value, String... keyVals) {
+        runtime.setProperties(key, value, keyVals);
+    }
+
+    @Override
+    public void addRoutes(RoutesBuilder builder) {
+        runtime.addRoutes(builder);
+    }
+
+    @Override
+    public void stop() throws Exception {
+        runtime.stop();
+    }
+
+    @Override
+    public void close() throws Exception {
+        runtime.close();
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return runtime.getCamelContext();
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/PropertiesSupport.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/PropertiesSupport.java
new file mode 100644
index 0000000000..61cda7d5d2
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/PropertiesSupport.java
@@ -0,0 +1,93 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.function.Predicate;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.spi.PropertyConfigurer;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.PropertyBindingSupport;
+import org.apache.camel.support.service.ServiceHelper;
+
+public final class PropertiesSupport {
+
+    private PropertiesSupport() {
+    }
+
+    public static <T> T bindProperties(CamelContext context, T target, String prefix) {
+        return bindProperties(context, target, prefix, false);
+    }
+
+    public static <T> T bindProperties(CamelContext context, T target, String prefix, boolean stripPrefix) {
+        return bindProperties(context, target, k -> k.startsWith(prefix), prefix, stripPrefix);
+    }
+
+    public static <T> T bindProperties(CamelContext context, T target, Predicate<String> filter, String prefix) {
+        return bindProperties(context, target, filter, prefix, false);
+    }
+
+    public static <T> T bindProperties(CamelContext context, T target, Predicate<String> filter, String prefix,
+            boolean stripPrefix) {
+        final PropertiesComponent component = context.getPropertiesComponent();
+        final Properties propertiesWithPrefix = component.loadProperties(filter);
+        final Map<String, Object> properties = new HashMap<>();
+
+        propertiesWithPrefix.stringPropertyNames().forEach(
+                name -> properties.put(
+                        stripPrefix ? name.substring(prefix.length()) : name,
+                        propertiesWithPrefix.getProperty(name)));
+
+        PropertyConfigurer configurer = null;
+        if (target instanceof Component) {
+            // the component needs to be initialized to have the configurer ready
+            ServiceHelper.initService(target);
+            configurer = ((Component) target).getComponentPropertyConfigurer();
+        }
+
+        if (configurer == null) {
+            String name = target.getClass().getName();
+            if (target instanceof ExtendedCamelContext) {
+                // special for camel context itself as we have an extended configurer
+                name = ExtendedCamelContext.class.getName();
+            }
+
+            // see if there is a configurer for it
+            configurer = PluginHelper.getConfigurerResolver(context.getCamelContextExtension()).resolvePropertyConfigurer(name,
+                    context);
+        }
+
+        PropertyBindingSupport.build()
+                .withIgnoreCase(true)
+                .withCamelContext(context)
+                .withTarget(target)
+                .withProperties(properties)
+                .withRemoveParameters(true)
+                .withOptionPrefix(stripPrefix ? null : prefix)
+                .withConfigurer(configurer)
+                .bind();
+
+        return target;
+    }
+
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RouteBuilders.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RouteBuilders.java
new file mode 100644
index 0000000000..e889f68bcd
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RouteBuilders.java
@@ -0,0 +1,73 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.io.Reader;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
+import org.apache.camel.quarkus.k.core.Source;
+import org.apache.camel.util.function.ThrowingBiConsumer;
+import org.apache.camel.util.function.ThrowingConsumer;
+
+public final class RouteBuilders {
+
+    private RouteBuilders() {
+    }
+
+    public static EndpointRouteBuilder endpoint(Source source,
+            ThrowingBiConsumer<Reader, EndpointRouteBuilder, Exception> consumer) {
+        return new EndpointRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                try (Reader reader = source.resolveAsReader(getContext())) {
+                    consumer.accept(reader, this);
+                }
+            }
+        };
+    }
+
+    public static EndpointRouteBuilder endpoint(ThrowingConsumer<EndpointRouteBuilder, Exception> consumer) {
+        return new EndpointRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                consumer.accept(this);
+            }
+        };
+    }
+
+    public static RoutesBuilder route(Source source, ThrowingBiConsumer<Reader, RouteBuilder, Exception> consumer) {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                try (Reader reader = source.resolveAsReader(getContext())) {
+                    consumer.accept(reader, this);
+                }
+            }
+        };
+    }
+
+    public static RoutesBuilder route(ThrowingConsumer<RouteBuilder, Exception> consumer) {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                consumer.accept(this);
+            }
+        };
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RuntimeSupport.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RuntimeSupport.java
new file mode 100644
index 0000000000..51a3caabb5
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/RuntimeSupport.java
@@ -0,0 +1,341 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.builder.RouteBuilderLifecycleStrategy;
+import org.apache.camel.quarkus.k.core.Source;
+import org.apache.camel.spi.CamelContextCustomizer;
+import org.apache.camel.spi.HasCamelContext;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class RuntimeSupport {
+    private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeSupport.class);
+
+    private RuntimeSupport() {
+    }
+
+    // *********************************
+    //
+    // Helpers - Customizers
+    //
+    // *********************************
+
+    public static List<CamelContextCustomizer> configureContextCustomizers(HasCamelContext hasCamelContext) {
+        return configureContextCustomizers(hasCamelContext.getCamelContext());
+    }
+
+    public static List<CamelContextCustomizer> configureContextCustomizers(CamelContext context) {
+        List<CamelContextCustomizer> appliedCustomizers = new ArrayList<>();
+        Map<String, CamelContextCustomizer> customizers = lookupCustomizers(context);
+
+        customizers.entrySet().stream()
+                .sorted(Map.Entry.comparingByValue())
+                .forEach(e -> {
+                    LOGGER.debug("Apply ContextCustomizer with id={} and type={}", e.getKey(),
+                            e.getValue().getClass().getName());
+
+                    PropertiesSupport.bindProperties(context, e.getValue(), Constants.CUSTOMIZER_PREFIX + e.getKey() + ".");
+                    PropertiesSupport.bindProperties(context, e.getValue(),
+                            Constants.CUSTOMIZER_PREFIX_FALLBACK + e.getKey() + ".");
+
+                    e.getValue().configure(context);
+
+                    appliedCustomizers.add(e.getValue());
+                });
+
+        return appliedCustomizers;
+    }
+
+    public static Map<String, CamelContextCustomizer> lookupCustomizers(CamelContext context) {
+        Map<String, CamelContextCustomizer> customizers = new ConcurrentHashMap<>();
+        Properties properties = context.getPropertiesComponent().loadProperties(
+                n -> n.startsWith(Constants.CUSTOMIZER_PREFIX) || n.startsWith(Constants.CUSTOMIZER_PREFIX_FALLBACK));
+
+        if (properties != null) {
+            //
+            // Lookup customizers listed in Constants.ENV_CAMEL_K_CUSTOMIZERS or Constants.PROPERTY_CAMEL_K_CUSTOMIZER
+            // for backward compatibility
+            //
+            for (String customizerId : lookupCustomizerIDs(context)) {
+                customizers.computeIfAbsent(customizerId, id -> lookupCustomizerByID(context, id));
+            }
+
+            Pattern pattern = Pattern.compile(Constants.ENABLE_CUSTOMIZER_PATTERN);
+
+            properties.entrySet().stream()
+                    .filter(entry -> entry.getKey() instanceof String)
+                    .filter(entry -> entry.getValue() != null)
+                    .forEach(entry -> {
+                        final String key = (String) entry.getKey();
+                        final Object val = entry.getValue();
+                        final Matcher matcher = pattern.matcher(key);
+
+                        if (matcher.matches()) {
+                            String customizerId = null;
+
+                            if (matcher.groupCount() == 1) {
+                                customizerId = matcher.group(1);
+                            } else if (matcher.groupCount() == 2) {
+                                customizerId = matcher.group(2);
+                            }
+
+                            if (customizerId != null && Boolean.parseBoolean(String.valueOf(val))) {
+                                //
+                                // Do not override customizers eventually found
+                                // in the registry
+                                //
+                                customizers.computeIfAbsent(customizerId, id -> lookupCustomizerByID(context, id));
+                            }
+                        }
+                    });
+        }
+
+        return customizers;
+    }
+
+    public static CamelContextCustomizer lookupCustomizerByID(CamelContext context, String customizerId) {
+        CamelContextCustomizer customizer = context.getRegistry().lookupByNameAndType(customizerId,
+                CamelContextCustomizer.class);
+        if (customizer == null) {
+            customizer = context.getCamelContextExtension()
+                    .getFactoryFinder(Constants.CONTEXT_CUSTOMIZER_RESOURCE_PATH)
+                    .newInstance(customizerId, CamelContextCustomizer.class)
+                    .orElseThrow(() -> new RuntimeException("Error creating instance for customizer: " + customizerId));
+
+            LOGGER.debug("Found customizer {} with id {} from service definition", customizer, customizerId);
+        } else {
+            LOGGER.debug("Found customizer {} with id {} from the registry", customizer, customizerId);
+        }
+
+        return customizer;
+    }
+
+    public static Set<String> lookupCustomizerIDs(CamelContext context) {
+        Set<String> customizers = new TreeSet<>();
+        String customizerIDs = System.getenv().getOrDefault(Constants.ENV_CAMEL_K_CUSTOMIZERS, "");
+        if (ObjectHelper.isEmpty(customizerIDs)) {
+            // TODO: getPropertiesComponent().resolveProperty() throws exception instead
+            //       of returning abd empty optional
+            customizerIDs = context.getPropertiesComponent()
+                    .loadProperties(Constants.PROPERTY_CAMEL_K_CUSTOMIZER::equals)
+                    .getProperty(Constants.PROPERTY_CAMEL_K_CUSTOMIZER, "");
+        }
+
+        if (ObjectHelper.isNotEmpty(customizerIDs)) {
+            for (String customizerId : customizerIDs.split(",", -1)) {
+                customizers.add(customizerId);
+            }
+        }
+        return customizers;
+    }
+
+    // *********************************
+    //
+    // Helpers - Interceptors
+    //
+    // *********************************
+
+    public static List<RouteBuilderLifecycleStrategy> loadInterceptors(CamelContext context, Source source) {
+        ExtendedCamelContext ecc = context.getCamelContextExtension();
+        List<RouteBuilderLifecycleStrategy> answer = new ArrayList<>();
+
+        for (String id : source.getInterceptors()) {
+            try {
+                // first check the registry
+                RouteBuilderLifecycleStrategy interceptor = ecc.getRegistry()
+                        .lookupByNameAndType(id, RouteBuilderLifecycleStrategy.class);
+
+                if (interceptor == null) {
+                    // then try with factory finder
+                    interceptor = ecc.getFactoryFinder(Constants.SOURCE_LOADER_INTERCEPTOR_RESOURCE_PATH)
+                            .newInstance(id, RouteBuilderLifecycleStrategy.class)
+                            .orElseThrow(
+                                    () -> new IllegalArgumentException("Unable to find source loader interceptor for: " + id));
+
+                    LOGGER.debug("Found source loader interceptor {} from service definition", id);
+                } else {
+                    LOGGER.debug("Found source loader interceptor {} from registry", id);
+                }
+
+                PropertiesSupport.bindProperties(context, interceptor, Constants.LOADER_INTERCEPTOR_PREFIX + id + ".");
+                PropertiesSupport.bindProperties(context, interceptor, Constants.LOADER_INTERCEPTOR_PREFIX_FALLBACK + id + ".");
+
+                answer.add(interceptor);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Unable to find source loader interceptor for: " + id, e);
+            }
+        }
+
+        return answer;
+    }
+
+    // *********************************
+    //
+    // Helpers - Misc
+    //
+    // *********************************
+
+    public static String getRuntimeVersion() {
+        String version = null;
+
+        InputStream is = null;
+        // try to load from maven properties first
+        try {
+            Properties p = new Properties();
+            is = RuntimeSupport.class.getResourceAsStream(
+                    "/META-INF/maven/org.apache.camel.quarkus/camel-quarkus-k-core-api/pom.properties");
+            if (is != null) {
+                p.load(is);
+                version = p.getProperty("version", "");
+            }
+        } catch (Exception e) {
+            // ignore
+        } finally {
+            if (is != null) {
+                IOHelper.close(is);
+            }
+        }
+
+        // fallback to using Java API
+        if (version == null) {
+            Package aPackage = RuntimeSupport.class.getPackage();
+            if (aPackage != null) {
+                version = aPackage.getImplementationVersion();
+                if (version == null) {
+                    version = aPackage.getSpecificationVersion();
+                }
+            }
+        }
+
+        if (version == null) {
+            // we could not compute the version so use a blank
+            version = "";
+        }
+
+        return Objects.requireNonNull(version, "Could not determine Camel K Runtime version");
+    }
+
+    // *********************************
+    //
+    // Properties
+    //
+    // *********************************
+
+    public static Map<String, String> loadApplicationProperties() {
+        final String conf = System.getProperty(Constants.PROPERTY_CAMEL_K_CONF, System.getenv(Constants.ENV_CAMEL_K_CONF));
+        final Map<String, String> properties = new HashMap<>();
+
+        if (ObjectHelper.isEmpty(conf)) {
+            return properties;
+        }
+
+        try {
+            Path confPath = Paths.get(conf);
+            if (Files.exists(confPath) && !Files.isDirectory(confPath)) {
+                try (Reader reader = Files.newBufferedReader(confPath)) {
+                    Properties p = new Properties();
+                    p.load(reader);
+                    p.forEach((key, value) -> properties.put(String.valueOf(key), String.valueOf(value)));
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return properties;
+    }
+
+    public static Map<String, String> loadUserProperties() {
+        final String conf = System.getProperty(Constants.PROPERTY_CAMEL_K_CONF_D, System.getenv(Constants.ENV_CAMEL_K_CONF_D));
+        final Map<String, String> properties = new HashMap<>();
+
+        if (ObjectHelper.isEmpty(conf)) {
+            return properties;
+        }
+
+        FileVisitor<Path> visitor = new SimpleFileVisitor<>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Objects.requireNonNull(file);
+                Objects.requireNonNull(attrs);
+
+                if (Files.isDirectory(file) || Files.isSymbolicLink(file)) {
+                    return FileVisitResult.CONTINUE;
+                }
+
+                if (file.toFile().getAbsolutePath().endsWith(".properties")) {
+                    try (Reader reader = Files.newBufferedReader(file)) {
+                        Properties p = new Properties();
+                        p.load(reader);
+                        p.forEach((key, value) -> properties.put(String.valueOf(key), String.valueOf(value)));
+                    }
+                } else {
+                    try {
+                        properties.put(
+                                file.getFileName().toString(),
+                                Files.readString(file, StandardCharsets.UTF_8));
+                    } catch (MalformedInputException mie) {
+                        // Just skip if it is not a UTF-8 encoded file (ie a binary)
+                        LOGGER.info("Cannot transform {} into UTF-8 text, skipping.", file);
+                    }
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        };
+
+        Path root = Paths.get(conf);
+
+        if (Files.exists(root)) {
+            try {
+                Files.walkFileTree(root, visitor);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        return properties;
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Sources.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Sources.java
new file mode 100644
index 0000000000..faf3a6b7e0
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/Sources.java
@@ -0,0 +1,243 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.quarkus.k.core.Source;
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.core.SourceType;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+
+public final class Sources {
+
+    private Sources() {
+    }
+
+    public static Source fromURI(String uri) throws Exception {
+        return fromDefinition(computeDefinitionFromURI(uri));
+    }
+
+    public static SourceDefinition fromBytes(String id, String name, String language, String loader, List<String> interceptors,
+            byte[] content) {
+        SourceDefinition answer = new SourceDefinition();
+        answer.setId(id);
+        answer.setName(name);
+        answer.setLanguage(language);
+        answer.setLoader(loader);
+        answer.setInterceptors(interceptors != null ? interceptors : Collections.emptyList());
+        answer.setContent(content);
+
+        return answer;
+    }
+
+    public static Source fromBytes(String name, String language, String loader, List<String> interceptors, byte[] content) {
+        return fromDefinition(fromBytes(null, name, language, loader, interceptors, content));
+    }
+
+    public static Source fromBytes(String name, String language, String loader, byte[] content) {
+        return fromDefinition(fromBytes(null, name, language, loader, null, content));
+    }
+
+    public static Source fromBytes(String language, byte[] content) {
+        return fromDefinition(fromBytes(null, UUID.randomUUID().toString(), language, null, null, content));
+    }
+
+    public static Source fromDefinition(SourceDefinition definition) {
+        if (definition.getLocation() == null && definition.getContent() == null) {
+            throw new IllegalArgumentException("Either the source location or the source content should be set");
+        }
+        return new Source() {
+            @Override
+            public String getLocation() {
+                return definition.getLocation();
+            }
+
+            @Override
+            public String getId() {
+                return ObjectHelper.supplyIfEmpty(definition.getId(), this::getName);
+            }
+
+            @Override
+            public String getName() {
+                String answer = definition.getName();
+                if (ObjectHelper.isEmpty(answer) && ObjectHelper.isNotEmpty(definition.getLocation())) {
+                    answer = StringSupport.substringAfter(definition.getLocation(), ":");
+                    answer = StringSupport.substringBeforeLast(answer, ".");
+
+                    if (answer.contains("/")) {
+                        answer = StringSupport.substringAfterLast(answer, "/");
+                    }
+                }
+
+                return answer;
+            }
+
+            @Override
+            public String getLanguage() {
+                String answer = definition.getLanguage();
+                if (ObjectHelper.isEmpty(answer) && ObjectHelper.isNotEmpty(definition.getLocation())) {
+                    answer = StringSupport.substringAfterLast(definition.getLocation(), ":");
+                    answer = StringSupport.substringAfterLast(answer, ".");
+                }
+
+                return answer;
+            }
+
+            @Override
+            public SourceType getType() {
+                return ObjectHelper.supplyIfEmpty(definition.getType(), () -> SourceType.source);
+            }
+
+            @Override
+            public Optional<String> getLoader() {
+                return Optional.ofNullable(definition.getLoader());
+            }
+
+            @Override
+            public List<String> getInterceptors() {
+                return ObjectHelper.supplyIfEmpty(definition.getInterceptors(), Collections::emptyList);
+            }
+
+            @Override
+            public List<String> getPropertyNames() {
+                return ObjectHelper.supplyIfEmpty(definition.getPropertyNames(), Collections::emptyList);
+            }
+
+            /**
+             * Read the content of the source as {@link InputStream}.
+             *
+             * @param  ctx the {@link CamelContext}
+             * @return     the {@link InputStream} representing the source content
+             */
+            @Override
+            public InputStream resolveAsInputStream(CamelContext ctx) {
+                try {
+                    InputStream is;
+
+                    if (definition.getContent() != null) {
+                        is = new ByteArrayInputStream(definition.getContent());
+                    } else {
+                        is = ResourceHelper.resolveMandatoryResourceAsInputStream(ctx, definition.getLocation());
+                    }
+
+                    return definition.isCompressed()
+                            ? new GZIPInputStream(Base64.getDecoder().wrap(is))
+                            : is;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+    }
+
+    // ******************************
+    //
+    // Helpers
+    //
+    // ******************************
+
+    public static Resource asResource(CamelContext camelContext, Source source) {
+        return new Resource() {
+            @Override
+            public String getLocation() {
+                return source.getLocation();
+            }
+
+            @Override
+            public boolean exists() {
+                return true;
+            }
+
+            @Override
+            public InputStream getInputStream() throws IOException {
+                return source.resolveAsInputStream(camelContext);
+            }
+
+            @Override
+            public Reader getReader() throws Exception {
+                return source.resolveAsReader(camelContext);
+            }
+
+            @Override
+            public Reader getReader(Charset charset) throws Exception {
+                return source.resolveAsReader(camelContext, charset);
+            }
+
+            @Override
+            public String getScheme() {
+                return source.getLocation();
+            }
+        };
+    }
+
+    public static SourceDefinition computeDefinitionFromURI(String uri) throws Exception {
+        final String location = StringSupport.substringBefore(uri, "?");
+
+        if (!location.startsWith(Constants.SCHEME_PREFIX_CLASSPATH) && !location.startsWith(Constants.SCHEME_PREFIX_FILE)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + uri);
+        }
+
+        final String query = StringSupport.substringAfter(uri, "?");
+        final Map<String, Object> params = URISupport.parseQuery(query);
+
+        String language = (String) params.get("language");
+        if (ObjectHelper.isEmpty(language)) {
+            language = StringSupport.substringAfterLast(location, ":");
+            language = StringSupport.substringAfterLast(language, ".");
+        }
+        if (ObjectHelper.isEmpty(language)) {
+            throw new IllegalArgumentException("Unknown language " + language);
+        }
+
+        String name = (String) params.get("name");
+        if (name == null) {
+            name = StringSupport.substringAfter(location, ":");
+            name = StringSupport.substringBeforeLast(name, ".");
+
+            if (name.contains("/")) {
+                name = StringSupport.substringAfterLast(name, "/");
+            }
+        }
+
+        SourceDefinition answer = new SourceDefinition();
+        answer.setId((String) params.get("id"));
+        answer.setLocation(location);
+        answer.setName(name);
+        answer.setLanguage(language);
+        answer.setLoader((String) params.get("loader"));
+        answer.setInterceptors(StringSupport.split((String) params.get("interceptors"), ","));
+        answer.setCompressed(Boolean.parseBoolean((String) params.get("compression")));
+
+        return answer;
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/SourcesSupport.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/SourcesSupport.java
new file mode 100644
index 0000000000..d88e115e1d
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/SourcesSupport.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.quarkus.k.support;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.RouteBuilderLifecycleStrategy;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RouteTemplateDefinition;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.k.core.RuntimeAware;
+import org.apache.camel.quarkus.k.core.Source;
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.listener.AbstractPhaseListener;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SourcesSupport {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SourcesSupport.class);
+
+    private SourcesSupport() {
+    }
+
+    public static Runtime.Listener forRoutes(String... sources) {
+        return new AbstractPhaseListener(Runtime.Phase.ConfigureRoutes) {
+            @Override
+            protected void accept(Runtime runtime) {
+                loadSources(runtime, sources);
+            }
+        };
+    }
+
+    public static Runtime.Listener forRoutes(SourceDefinition... definitions) {
+        return new AbstractPhaseListener(Runtime.Phase.ConfigureRoutes) {
+            @Override
+            protected void accept(Runtime runtime) {
+                loadSources(runtime, definitions);
+            }
+        };
+    }
+
+    public static void loadSources(Runtime runtime, String... routes) {
+        for (String route : routes) {
+            if (ObjectHelper.isEmpty(route)) {
+                continue;
+            }
+
+            LOGGER.info("Loading routes from: {}", route);
+
+            try {
+                load(runtime, Sources.fromURI(route));
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+        }
+    }
+
+    public static void loadSources(Runtime runtime, SourceDefinition... definitions) {
+        for (SourceDefinition definition : definitions) {
+            LOGGER.info("Loading routes from: {}", definition);
+
+            load(runtime, Sources.fromDefinition(definition));
+        }
+    }
+
+    public static void load(Runtime runtime, Source source) {
+        final List<RouteBuilderLifecycleStrategy> interceptors;
+
+        switch (source.getType()) {
+        case source:
+            interceptors = RuntimeSupport.loadInterceptors(runtime.getCamelContext(), source);
+            interceptors.forEach(interceptor -> {
+                if (interceptor instanceof RuntimeAware) {
+                    ((RuntimeAware) interceptor).setRuntime(runtime);
+                }
+            });
+
+            break;
+        case template:
+            if (!source.getInterceptors().isEmpty()) {
+                LOGGER.warn("Interceptors associated to the route template {} will be ignored", source.getName());
+            }
+
+            interceptors = List.of(new RouteBuilderLifecycleStrategy() {
+                @Override
+                public void afterConfigure(RouteBuilder builder) {
+                    List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
+                    List<RouteTemplateDefinition> templates = builder.getRouteTemplateCollection().getRouteTemplates();
+
+                    if (routes.size() != 1) {
+                        throw new IllegalArgumentException(
+                                "There should be a single route definition when configuring route templates, got "
+                                        + routes.size());
+                    }
+                    if (!templates.isEmpty()) {
+                        throw new IllegalArgumentException(
+                                "There should not be any template definition when configuring route templates, got "
+                                        + templates.size());
+                    }
+
+                    // create a new template from the source
+                    RouteTemplateDefinition templatesDefinition = builder.getRouteTemplateCollection()
+                            .routeTemplate(source.getId());
+                    templatesDefinition.setRoute(routes.get(0));
+
+                    source.getPropertyNames().forEach(templatesDefinition::templateParameter);
+
+                    // remove all routes definitions as they have been translated
+                    // in the related route template
+                    routes.clear();
+                }
+            });
+            break;
+        case errorHandler:
+            if (!source.getInterceptors().isEmpty()) {
+                LOGGER.warn("Interceptors associated to the error handler {} will be ignored", source.getName());
+            }
+
+            interceptors = List.of(new RouteBuilderLifecycleStrategy() {
+                @Override
+                public void afterConfigure(RouteBuilder builder) {
+                    List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
+                    List<RouteTemplateDefinition> templates = builder.getRouteTemplateCollection().getRouteTemplates();
+
+                    if (!routes.isEmpty()) {
+                        throw new IllegalArgumentException(
+                                "There should be no route definition when configuring error handler, got " + routes.size());
+                    }
+                    if (!templates.isEmpty()) {
+                        throw new IllegalArgumentException(
+                                "There should not be any template definition when configuring error handler, got "
+                                        + templates.size());
+                    }
+                    if (builder.hasErrorHandlerFactory()) {
+                        LOGGER.debug("Setting default error handler builder factory as type {}",
+                                builder.getErrorHandlerFactory().getClass());
+                        runtime.getExtendedCamelContext().setErrorHandlerFactory(builder.getErrorHandlerFactory());
+                    }
+                }
+            });
+            break;
+        default:
+            throw new IllegalArgumentException("Unknown source type: " + source.getType());
+        }
+
+        try {
+            final Resource resource = Sources.asResource(runtime.getCamelContext(), source);
+            final ExtendedCamelContext ecc = runtime.getExtendedCamelContext();
+            final Collection<RoutesBuilder> builders = PluginHelper.getRoutesLoader(ecc).findRoutesBuilders(resource);
+
+            builders.stream()
+                    .map(RouteBuilder.class::cast)
+                    .peek(b -> interceptors.forEach(b::addLifecycleInterceptor))
+                    .forEach(runtime::addRoutes);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+    public static void loadErrorHandlerSource(Runtime runtime, SourceDefinition errorHandlerSourceDefinition) {
+        LOGGER.info("Loading error handler from: {}", errorHandlerSourceDefinition);
+        load(runtime, Sources.fromDefinition(errorHandlerSourceDefinition));
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/StringSupport.java b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/StringSupport.java
new file mode 100644
index 0000000000..370f6fc7f8
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/java/org/apache/camel/quarkus/k/support/StringSupport.java
@@ -0,0 +1,75 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+
+public final class StringSupport {
+    private StringSupport() {
+    }
+
+    public static String substringBefore(String str, String separator) {
+        String answer = StringHelper.before(str, separator);
+        if (answer == null) {
+            answer = str;
+        }
+
+        return answer;
+    }
+
+    public static String substringAfter(String str, String separator) {
+        String answer = StringHelper.after(str, separator);
+        if (answer == null) {
+            answer = "";
+        }
+
+        return answer;
+    }
+
+    public static String substringAfterLast(String str, String separator) {
+        if (ObjectHelper.isEmpty(str)) {
+            return str;
+        }
+        if (ObjectHelper.isEmpty(separator)) {
+            return "";
+        }
+        int pos = str.lastIndexOf(separator);
+        if (pos == -1 || pos == str.length() - separator.length()) {
+            return "";
+        }
+        return str.substring(pos + separator.length());
+    }
+
+    public static String substringBeforeLast(String str, String separator) {
+        if (ObjectHelper.isEmpty(str) || ObjectHelper.isEmpty(separator)) {
+            return str;
+        }
+        int pos = str.lastIndexOf(separator);
+        if (pos == -1) {
+            return str;
+        }
+        return str.substring(0, pos);
+    }
+
+    public static List<String> split(String input, String regex) {
+        return input != null ? List.of(input.split(regex)) : Collections.emptyList();
+    }
+}
diff --git a/extensions/camel-k/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/camel-k/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000000..61d12cde1c
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+# This is a generated file. Do not edit directly!
+# To re-generate, run the following command from the top level directory:
+#
+#   mvn -N cq:update-quarkus-metadata
+#
+---
+name: "Camel K"
+description: "Camel runtime specialization for Camel K"
+icon-url: "https://camel.apache.org/_/img/logo-d-f21b25ba38.svg"
+metadata:
+  unlisted: true
+  guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/camel-k.html"
+  categories:
+  - "integration"
+  status:
+  - "stable"
diff --git a/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.apache.camel.quarkus.k.core.Runtime$Listener b/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.apache.camel.quarkus.k.core.Runtime$Listener
new file mode 100644
index 0000000000..bdd638af63
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.apache.camel.quarkus.k.core.Runtime$Listener
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.camel.quarkus.k.listener.ContextConfigurer
+org.apache.camel.quarkus.k.listener.SourcesConfigurer
diff --git a/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider b/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider
new file mode 100644
index 0000000000..060b38082f
--- /dev/null
+++ b/extensions/camel-k/runtime/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+org.apache.camel.quarkus.k.runtime.ApplicationConfigSourceProvider
\ No newline at end of file
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/SourceTest.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/SourceTest.java
new file mode 100644
index 0000000000..7942c0295c
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/SourceTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.quarkus.k;
+
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.support.Sources;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
+
+public class SourceTest {
+    @Test
+    public void testResourceWithoutScheme() {
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
+                () -> Sources.fromURI("routes.js"));
+    }
+
+    @Test
+    public void testResourceWithIllegalScheme() {
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
+                () -> Sources.fromURI("http:routes.js"));
+    }
+
+    @Test
+    public void testUnsupportedLanguage() {
+        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
+                () -> Sources.fromURI("  test"));
+    }
+
+    @Test
+    public void sourceCanBeContructedFromLocation() {
+        SourceDefinition definition = new SourceDefinition();
+        definition.setLocation("classpath:MyRoutes.java");
+
+        assertThat(Sources.fromDefinition(definition))
+                .hasFieldOrPropertyWithValue("name", "MyRoutes")
+                .hasFieldOrPropertyWithValue("language", "java");
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/PropertiesFunctionsConfigurerTest.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/PropertiesFunctionsConfigurerTest.java
new file mode 100644
index 0000000000..b715c6b991
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/PropertiesFunctionsConfigurerTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.quarkus.k.listener;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class PropertiesFunctionsConfigurerTest {
+
+    @Test
+    public void testKubernetesFunction() {
+        Runtime runtime = Runtime.on(new DefaultCamelContext());
+        runtime.setProperties("my.property", "{{secret:my-secret/my-property}}");
+
+        assertThat(runtime.getCamelContext().resolvePropertyPlaceholders("{{secret:my-secret/my-property}}"))
+                .isEqualTo("my-secret-property");
+        assertThat(runtime.getCamelContext().resolvePropertyPlaceholders("{{secret:none/my-property:my-default-secret}}"))
+                .isEqualTo("my-default-secret");
+        CamelContext context = runtime.getCamelContext();
+
+        assertThatThrownBy(() -> context.resolvePropertyPlaceholders("{{secret:none/my-property}}"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("returned null value which is not allowed, from input");
+
+        assertThat(runtime.getCamelContext().resolvePropertyPlaceholders("{{configmap:my-cm/my-property}}"))
+                .isEqualTo("my-cm-property");
+        assertThat(runtime.getCamelContext().resolvePropertyPlaceholders("{{configmap:my-cm/my-property:my-default-cm}}"))
+                .isEqualTo("my-default-cm");
+
+        assertThatThrownBy(() -> context.resolvePropertyPlaceholders("{{configmap:none/my-property}}"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("returned null value which is not allowed, from input");
+
+        assertThat(runtime.getCamelContext().resolvePropertyPlaceholders("{{my.property}}")).isEqualTo("my-secret-property");
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/SourceConfigurerTest.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/SourceConfigurerTest.java
new file mode 100644
index 0000000000..9a727d855e
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/listener/SourceConfigurerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.quarkus.k.listener;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.quarkus.k.core.SourceType;
+import org.apache.camel.quarkus.k.support.PropertiesSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.util.PropertiesHelper.asProperties;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SourceConfigurerTest {
+    @Test
+    public void shouldLoadMultipleSources() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "templateName",
+                "camel.k.sources[0].location", "classpath:MyTemplate.java",
+                "camel.k.sources[0].type", "template",
+                "camel.k.sources[1].name", "src",
+                "camel.k.sources[1].location", "classpath:MySrc.java",
+                "camel.k.sources[2].name", "err",
+                "camel.k.sources[2].location", "classpath:Err.java",
+                "camel.k.sources[2].type", "errorHandler"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+
+        assertThat(configuration.getSources()).hasSize(3);
+    }
+
+    @Test
+    public void shouldFailOnMultipleErrorHandlers() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "templateName0",
+                "camel.k.sources[0].location", "classpath:MyTemplate1.java",
+                "camel.k.sources[0].type", "template",
+                "camel.k.sources[1].name", "err1",
+                "camel.k.sources[1].location", "classpath:Err1.java",
+                "camel.k.sources[1].type", "errorHandler",
+                "camel.k.sources[2].name", "err2",
+                "camel.k.sources[2].location", "classpath:Err2.java",
+                "camel.k.sources[2].type", "errorHandler"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+
+        assertThat(configuration.getSources()).hasSize(3);
+        Assertions.assertThrows(IllegalArgumentException.class, () -> {
+            SourcesConfigurer.checkUniqueErrorHandler(configuration.getSources());
+        }, "java.lang.IllegalArgumentException: Expected only one error handler source type, got 2");
+    }
+
+    @Test
+    public void shouldDefaultSourcesWithEmptyType() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "source0",
+                "camel.k.sources[1].name", "source1",
+                "camel.k.sources[2].name", "source2",
+                "camel.k.sources[2].type", "source"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+
+        assertThat(configuration.getSources().length).isEqualTo(3);
+        assertThat(configuration.getSources()[0].getType()).isEqualTo(SourceType.source);
+        assertThat(configuration.getSources()[1].getType()).isEqualTo(SourceType.source);
+        assertThat(configuration.getSources()[2].getType()).isEqualTo(SourceType.source);
+    }
+
+    @Test
+    public void shouldOrderSourcesByType() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "template1",
+                "camel.k.sources[0].type", "template",
+                "camel.k.sources[1].name", "source1",
+                "camel.k.sources[1].type", "source",
+                "camel.k.sources[2].name", "source2",
+                "camel.k.sources[3].name", "errorHandler1",
+                "camel.k.sources[3].type", "errorHandler"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+        SourcesConfigurer.sortSources(configuration.getSources());
+
+        assertThat(configuration.getSources()).hasSize(4);
+        assertThat(configuration.getSources()[0].getName()).isEqualTo("errorHandler1");
+        assertThat(configuration.getSources()[0].getType()).isEqualTo(SourceType.errorHandler);
+        assertThat(configuration.getSources()[1].getName()).isEqualTo("template1");
+        assertThat(configuration.getSources()[1].getType()).isEqualTo(SourceType.template);
+        // Order for the same type does not matter
+        assertThat(configuration.getSources()[2].getName()).contains("source");
+        assertThat(configuration.getSources()[2].getType()).isEqualTo(SourceType.source);
+        assertThat(configuration.getSources()[3].getName()).contains("source");
+        assertThat(configuration.getSources()[3].getType()).isEqualTo(SourceType.source);
+    }
+
+    @Test
+    public void shouldNotFailOnEmptySources() {
+        SourcesConfigurer.sortSources(null);
+        SourcesConfigurer.checkUniqueErrorHandler(null);
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/NameCustomizer.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/NameCustomizer.java
new file mode 100644
index 0000000000..e0033e3f1a
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/NameCustomizer.java
@@ -0,0 +1,45 @@
+/*
+ * 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.quarkus.k.support;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Ordered;
+import org.apache.camel.impl.engine.ExplicitCamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextCustomizer;
+
+public final class NameCustomizer implements CamelContextCustomizer {
+
+    private String name;
+
+    public NameCustomizer() {
+        this("default");
+    }
+
+    public NameCustomizer(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public int getOrder() {
+        return Ordered.HIGHEST;
+    }
+
+    @Override
+    public void configure(CamelContext camelContext) {
+        camelContext.setNameStrategy(new ExplicitCamelContextNameStrategy(name));
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/PropertiesSupportTest.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/PropertiesSupportTest.java
new file mode 100644
index 0000000000..2c11d02d19
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/PropertiesSupportTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.quarkus.k.support;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.quarkus.k.core.SourceDefinition;
+import org.apache.camel.quarkus.k.listener.SourcesConfigurer;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.util.PropertiesHelper.asProperties;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PropertiesSupportTest {
+    @Test
+    public void propertiesAreBoundToSourcesConfigurer() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "MyRoutesWithBeans",
+                "camel.k.sources[0].location", "classpath:MyRoutesWithBeans.java",
+                "camel.k.sources[1].name", "MyRoutesConfig",
+                "camel.k.sources[1].location", "classpath:MyRoutesConfig.java",
+                "camel.k.sources[1].property-names[0]", "foo",
+                "camel.k.sources[1].property-names[1]", "bar"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+
+        assertThat(configuration.getSources())
+                .hasSize(2)
+                .anyMatch(byNameAndLocation("MyRoutesWithBeans", "classpath:MyRoutesWithBeans.java")
+                        .and(d -> d.getPropertyNames() == null))
+                .anyMatch(byNameAndLocation("MyRoutesConfig", "classpath:MyRoutesConfig.java")
+                        .and(d -> d.getPropertyNames() != null && d.getPropertyNames().containsAll(List.of("foo", "bar"))));
+    }
+
+    @Test
+    public void propertiesWithGapsAreBoundToSourcesConfigurer() {
+        CamelContext context = new DefaultCamelContext();
+        context.getPropertiesComponent().setInitialProperties(asProperties(
+                "camel.k.sources[0].name", "MyRoutesWithBeans",
+                "camel.k.sources[0].location", "classpath:MyRoutesWithBeans.java",
+                "camel.k.sources[2].name", "MyRoutesConfig",
+                "camel.k.sources[2].location", "classpath:MyRoutesConfig.java"));
+
+        SourcesConfigurer configuration = new SourcesConfigurer();
+
+        PropertiesSupport.bindProperties(
+                context,
+                configuration,
+                k -> k.startsWith(SourcesConfigurer.CAMEL_K_SOURCES_PREFIX),
+                SourcesConfigurer.CAMEL_K_PREFIX);
+
+        assertThat(configuration.getSources())
+                .hasSize(3)
+                .filteredOn(Objects::nonNull)
+                .hasSize(2)
+                .anyMatch(byNameAndLocation("MyRoutesWithBeans", "classpath:MyRoutesWithBeans.java"))
+                .anyMatch(byNameAndLocation("MyRoutesConfig", "classpath:MyRoutesConfig.java"));
+    }
+
+    // ***************************
+    //
+    // Helpers
+    //
+    // ***************************
+
+    private static Predicate<SourceDefinition> byNameAndLocation(String name, String location) {
+        return def -> Objects.equals(def.getName(), name) && Objects.equals(def.getLocation(), location);
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/RuntimeSupportTest.java b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/RuntimeSupportTest.java
new file mode 100644
index 0000000000..393ba49370
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/java/org/apache/camel/quarkus/k/support/RuntimeSupportTest.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.quarkus.k.support;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Ordered;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.engine.ExplicitCamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextCustomizer;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RuntimeSupportTest {
+
+    @Test
+    public void testLoadCustomizersWithPropertiesFlags() {
+        CamelContext context = new DefaultCamelContext();
+
+        NameCustomizer customizer = new NameCustomizer("from-registry");
+        context.getRegistry().bind("name", customizer);
+
+        List<CamelContextCustomizer> customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isNotEqualTo("from-registry");
+        assertThat(context.getName()).isNotEqualTo("default");
+        assertThat(customizers).isEmpty();
+
+        Properties properties = new Properties();
+        properties.setProperty("camel.k.customizer.name.enabled", "true");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("from-registry");
+        assertThat(customizers).hasSize(1);
+    }
+
+    @Test
+    public void testLoadCustomizersWithList() {
+        CamelContext context = new DefaultCamelContext();
+
+        NameCustomizer customizer = new NameCustomizer("from-registry");
+        context.getRegistry().bind("name", customizer);
+
+        List<CamelContextCustomizer> customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isNotEqualTo("from-registry");
+        assertThat(context.getName()).isNotEqualTo("default");
+        assertThat(customizers).isEmpty();
+
+        Properties properties = new Properties();
+        properties.setProperty(Constants.PROPERTY_CAMEL_K_CUSTOMIZER, "name");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("from-registry");
+        assertThat(customizers).hasSize(1);
+    }
+
+    @Test
+    public void testLoadCustomizers() {
+        CamelContext context = new DefaultCamelContext();
+        context.getRegistry().bind("converters",
+                (CamelContextCustomizer) camelContext -> camelContext.setLoadTypeConverters(true));
+
+        List<CamelContextCustomizer> customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isNotEqualTo("from-registry");
+        assertThat(context.getName()).isNotEqualTo("default");
+        assertThat(context.isLoadTypeConverters()).isFalse();
+        assertThat(customizers).isEmpty();
+
+        Properties properties = new Properties();
+        properties.setProperty("camel.k.customizer.name.enabled", "true");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("default");
+        assertThat(customizers).hasSize(1);
+
+        properties.setProperty("camel.k.customizer.converters.enabled", "true");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("default");
+        assertThat(context.isLoadTypeConverters()).isTrue();
+        assertThat(customizers).hasSize(2);
+    }
+
+    @Test
+    public void testLoadCustomizersFallback() {
+        CamelContext context = new DefaultCamelContext();
+        context.getRegistry().bind("converters",
+                (CamelContextCustomizer) camelContext -> camelContext.setLoadTypeConverters(true));
+
+        List<CamelContextCustomizer> customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isNotEqualTo("from-registry");
+        assertThat(context.getName()).isNotEqualTo("default");
+        assertThat(context.isLoadTypeConverters()).isFalse();
+        assertThat(customizers).isEmpty();
+
+        Properties properties = new Properties();
+        properties.setProperty("customizer.name.enabled", "true");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("default");
+        assertThat(customizers).hasSize(1);
+
+        properties.setProperty("customizer.converters.enabled", "true");
+        properties.setProperty("customizer.converters.enabled", "true");
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(context.getName()).isEqualTo("default");
+        assertThat(context.isLoadTypeConverters()).isTrue();
+        assertThat(customizers).hasSize(2);
+    }
+
+    @Test
+    public void testLoadCustomizerOrder() {
+        DefaultCamelContext context = new DefaultCamelContext();
+        context.setName("camel");
+        context.getRegistry().bind("c1", new CamelContextCustomizer() {
+            @Override
+            public int getOrder() {
+                return Ordered.LOWEST;
+            }
+
+            @Override
+            public void configure(CamelContext camelContext) {
+                camelContext.setNameStrategy(new ExplicitCamelContextNameStrategy(camelContext.getName() + "-c1"));
+            }
+        });
+        context.getRegistry().bind("c2", new CamelContextCustomizer() {
+            @Override
+            public int getOrder() {
+                return Ordered.HIGHEST;
+            }
+
+            @Override
+            public void configure(CamelContext camelContext) {
+                camelContext.setNameStrategy(new ExplicitCamelContextNameStrategy(camelContext.getName() + "-c2"));
+            }
+        });
+        context.getRegistry().bind("c3", new CamelContextCustomizer() {
+            @Override
+            public void configure(CamelContext camelContext) {
+                camelContext.setNameStrategy(new ExplicitCamelContextNameStrategy(camelContext.getName() + "-c3"));
+            }
+        });
+
+        Properties properties = new Properties();
+        properties.setProperty("camel.k.customizer.c1.enabled", "true");
+        properties.setProperty("camel.k.customizer.c2.enabled", "true");
+        properties.setProperty("camel.k.customizer.c3.enabled", "true");
+
+        context.getPropertiesComponent().setInitialProperties(properties);
+
+        List<CamelContextCustomizer> customizers = RuntimeSupport.configureContextCustomizers(context);
+        assertThat(customizers).hasSize(3);
+        assertThat(context.getName()).isEqualTo("camel-c2-c3-c1");
+    }
+
+    @Test
+    public void shouldLoadUsePropertiesFromTextConfigMap() {
+        System.setProperty(Constants.PROPERTY_CAMEL_K_CONF_D, getClass().getResource("/configmaps/my-cm").getFile());
+        Map<String, String> loadedProperties = RuntimeSupport.loadUserProperties();
+        assertThat(loadedProperties).hasSize(1);
+        assertThat(loadedProperties.get("my-property")).isEqualTo("my-cm-property");
+    }
+
+    @Test
+    public void shouldSkipLoadUsePropertiesFromBinaryConfigMap() {
+        System.setProperty(Constants.PROPERTY_CAMEL_K_CONF_D, getClass().getResource("/configmaps/my-binary-cm").getFile());
+        Map<String, String> loadedProperties = RuntimeSupport.loadUserProperties();
+        assertThat(loadedProperties).isEmpty();
+    }
+}
diff --git a/extensions/camel-k/runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/name b/extensions/camel-k/runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/name
new file mode 100644
index 0000000000..26286751d8
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/name
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.quarkus.k.support.NameCustomizer
\ No newline at end of file
diff --git a/extensions/camel-k/runtime/src/test/resources/configmaps/my-binary-cm/my-property.zip b/extensions/camel-k/runtime/src/test/resources/configmaps/my-binary-cm/my-property.zip
new file mode 100644
index 0000000000..39610526e3
Binary files /dev/null and b/extensions/camel-k/runtime/src/test/resources/configmaps/my-binary-cm/my-property.zip differ
diff --git a/extensions/camel-k/runtime/src/test/resources/configmaps/my-cm/my-property b/extensions/camel-k/runtime/src/test/resources/configmaps/my-cm/my-property
new file mode 100644
index 0000000000..38c6ea5bd6
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/resources/configmaps/my-cm/my-property
@@ -0,0 +1 @@
+my-cm-property
\ No newline at end of file
diff --git a/extensions/camel-k/runtime/src/test/resources/my-cp-resource.txt b/extensions/camel-k/runtime/src/test/resources/my-cp-resource.txt
new file mode 100644
index 0000000000..64ec491e4d
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/resources/my-cp-resource.txt
@@ -0,0 +1 @@
+my cp content
\ No newline at end of file
diff --git a/extensions/camel-k/runtime/src/test/resources/my-file-resource.txt b/extensions/camel-k/runtime/src/test/resources/my-file-resource.txt
new file mode 100644
index 0000000000..63d3cca605
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/resources/my-file-resource.txt
@@ -0,0 +1 @@
+my file content
\ No newline at end of file
diff --git a/extensions/camel-k/runtime/src/test/resources/secrets/my-secret/my-property b/extensions/camel-k/runtime/src/test/resources/secrets/my-secret/my-property
new file mode 100644
index 0000000000..01b39e434e
--- /dev/null
+++ b/extensions/camel-k/runtime/src/test/resources/secrets/my-secret/my-property
@@ -0,0 +1 @@
+my-secret-property
\ No newline at end of file
diff --git a/extensions/pom.xml b/extensions/pom.xml
index f318d7f4d8..ab26cb300d 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -72,6 +72,7 @@
         <module>braintree</module>
         <module>browse</module>
         <module>caffeine</module>
+        <module>camel-k</module>
         <module>cassandraql</module>
         <module>cbor</module>
         <module>cloudevents</module>
diff --git a/integration-tests/camel-k-runtime/pom.xml b/integration-tests/camel-k-runtime/pom.xml
new file mode 100644
index 0000000000..43d862feb0
--- /dev/null
+++ b/integration-tests/camel-k-runtime/pom.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent-it</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../../poms/build-parent-it/pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-integration-test-camel-k-runtime</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: Camel K Runtime</name>
+    <description>Integration tests for Camel Quarkus K Runtime extension</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-camel-k</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-yaml-dsl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-xml-io-dsl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-timer</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-log</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-rest</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-platform-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-knative</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jsonb</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jsonb</artifactId>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <environmentVariables>
+                        <CAMEL_K_CONF>${project.basedir}/src/test/resources/conf.properties</CAMEL_K_CONF>
+                        <CAMEL_K_CONF_D>${project.basedir}/src/test/resources/conf.d</CAMEL_K_CONF_D>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <environmentVariables>
+                                        <CAMEL_K_CONF>${project.basedir}/src/test/resources/conf.properties</CAMEL_K_CONF>
+                                        <CAMEL_K_CONF_D>${project.basedir}/src/test/resources/conf.d</CAMEL_K_CONF_D>
+                                    </environmentVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>virtualDependencies</id>
+            <activation>
+                <property>
+                    <name>!noVirtualDependencies</name>
+                </property>
+            </activation>
+            <dependencies>
+                <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-yaml-dsl-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>skip-testcontainers-tests</id>
+            <activation>
+                <property>
+                    <name>skip-testcontainers-tests</name>
+                </property>
+            </activation>
+            <properties>
+                <skipTests>true</skipTests>
+            </properties>
+        </profile>
+    </profiles>
+</project>
diff --git a/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/Application.java b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/Application.java
new file mode 100644
index 0000000000..d498de2f60
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/Application.java
@@ -0,0 +1,108 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.util.Collections;
+import java.util.Map;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.main.BaseMainSupport;
+import org.apache.camel.quarkus.k.core.Runtime;
+import org.apache.camel.quarkus.main.CamelMain;
+
+import static org.apache.camel.quarkus.k.runtime.Application.instance;
+
+@Path("/camel-k")
+@ApplicationScoped
+public class Application {
+
+    @Inject
+    CamelContext camelContext;
+
+    @GET
+    @Path("/inspect")
+    @Produces(MediaType.APPLICATION_JSON)
+    @SuppressWarnings("unchecked")
+    public JsonObject inspect() {
+        return Json.createObjectBuilder()
+                .add(
+                        "camel-context",
+                        instance(CamelContext.class).map(Object::getClass).map(Class::getName).orElse(""))
+                .add(
+                        "camel-k-runtime",
+                        instance(Runtime.class).map(Object::getClass).map(Class::getName).orElse(""))
+                .add(
+                        "routes-collector",
+                        instance(CamelMain.class).map(BaseMainSupport::getRoutesCollector).map(Object::getClass)
+                                .map(Class::getName).orElse(""))
+                .add(
+                        "global-options",
+                        Json.createObjectBuilder(
+                                (Map) instance(CamelMain.class)
+                                        .map(BaseMainSupport::getCamelContext)
+                                        .map(CamelContext::getGlobalOptions)
+                                        .orElseGet(Collections::emptyMap))
+                                .build())
+                .build();
+    }
+
+    @GET
+    @Path("/inspect/context")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject inspectContext() {
+        return Json.createObjectBuilder()
+                .add("message-history", camelContext.isMessageHistory())
+                .add("load-type-converters", camelContext.isLoadTypeConverters())
+                .add("name", camelContext.getName())
+                .build();
+    }
+
+    @GET
+    @Path("/property/{name}")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String property(@PathParam("name") String name) {
+        return instance(CamelContext.class)
+                .map(CamelContext::getPropertiesComponent)
+                .map(PropertiesComponent.class::cast)
+                .flatMap(pc -> pc.resolveProperty(name)).orElse("");
+    }
+
+    @SuppressWarnings("unchecked")
+    @GET
+    @Path("/properties")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject properties() {
+        return Json.createObjectBuilder(
+                instance(CamelContext.class)
+                        .map(CamelContext::getPropertiesComponent)
+                        .map(PropertiesComponent.class::cast)
+                        .map(PropertiesComponent::loadProperties)
+                        .map(Map.class::cast)
+                        .orElseGet(Collections::emptyMap))
+                .build();
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/RuntimeInspector.java b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/RuntimeInspector.java
new file mode 100644
index 0000000000..cb186d1c88
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/RuntimeInspector.java
@@ -0,0 +1,111 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.bind.Jsonb;
+import jakarta.json.bind.JsonbBuilder;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Route;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.ToDefinition;
+import org.apache.camel.model.rest.RestDefinition;
+import org.eclipse.microprofile.config.Config;
+
+import static org.apache.camel.model.ProcessorDefinitionHelper.filterTypeInOutputs;
+
+@Path("/camel-k/runtime")
+@ApplicationScoped
+public class RuntimeInspector {
+    @Inject
+    CamelContext camelContext;
+    @Inject
+    Config config;
+
+    @GET
+    @Path("/inspect")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonObject inspect() {
+        return Json.createObjectBuilder()
+                .add("routes", Json.createArrayBuilder(
+                        camelContext.getRoutes().stream()
+                                .map(Route::getId)
+                                .collect(Collectors.toList())))
+                .add("route-definitions", Json.createArrayBuilder(
+                        camelContext.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinitions().stream()
+                                .map(RouteDefinition::getId)
+                                .collect(Collectors.toList())))
+                .add("rest-definitions", Json.createArrayBuilder(
+                        camelContext.getCamelContextExtension().getContextPlugin(Model.class).getRestDefinitions().stream()
+                                .map(RestDefinition::getId)
+                                .collect(Collectors.toList())))
+                .build();
+    }
+
+    @GET
+    @Path("/property/{name}")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String property(@PathParam("name") String name) {
+        return config.getValue(name, String.class);
+    }
+
+    @GET
+    @Path("/registry/beans/{name}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public String bean(@PathParam("name") String name) throws Exception {
+        Object bean = camelContext.getRegistry().lookupByName(name);
+        if (bean == null) {
+            throw new IllegalArgumentException("Bean with name: " + name + " not found");
+        }
+
+        try (Jsonb jsonb = JsonbBuilder.create()) {
+            return jsonb.toJson(bean);
+        }
+    }
+
+    @GET
+    @Path("/route-outputs/{name}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonArray routeOutputs(@PathParam("name") String name) {
+        RouteDefinition def = camelContext.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinition(name);
+        if (def == null) {
+            throw new IllegalArgumentException("RouteDefinition with name: " + name + " not found");
+        }
+
+        Collection<ToDefinition> toDefinitions = filterTypeInOutputs(def.getOutputs(), ToDefinition.class);
+
+        List<String> endpoints = toDefinitions.stream()
+                .map(td -> td.getEndpointUri())
+                .collect(Collectors.toList());
+
+        return Json.createArrayBuilder(endpoints).build();
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/BeanProducers.java b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/BeanProducers.java
new file mode 100644
index 0000000000..f5d2f8c462
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/BeanProducers.java
@@ -0,0 +1,36 @@
+/*
+ * 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.quarkus.k.it.yaml;
+
+import io.quarkus.arc.Unremovable;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import org.apache.camel.component.knative.spi.Knative;
+import org.apache.camel.component.knative.spi.KnativeEnvironment;
+
+@ApplicationScoped
+public class BeanProducers {
+    @Unremovable
+    @Produces
+    KnativeEnvironment knativeEnvironment() {
+        return KnativeEnvironment.on(
+                KnativeEnvironment.serviceBuilder(Knative.Type.endpoint, "sink")
+                        .withUrl("http://localhost:8080")
+                        .withEndpointKind(Knative.EndpointKind.sink)
+                        .build());
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyBean.java b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyBean.java
new file mode 100644
index 0000000000..02ebd4d260
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyBean.java
@@ -0,0 +1,46 @@
+/*
+ * 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.quarkus.k.it.yaml;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
+public class MyBean {
+    private String name;
+
+    public MyBean() {
+    }
+
+    public MyBean(String name) {
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "MyBean{" +
+                "name='" + name + '\'' +
+                '}';
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyProcessor.java b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyProcessor.java
new file mode 100644
index 0000000000..75bc5bcfa9
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/java/org/apache/camel/quarkus/k/it/yaml/MyProcessor.java
@@ -0,0 +1,28 @@
+/*
+ * 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.quarkus.k.it.yaml;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+
+@RegisterForReflection
+public class MyProcessor implements Processor {
+    @Override
+    public void process(Exchange exchange) throws Exception {
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/main/resources/application.properties b/integration-tests/camel-k-runtime/src/main/resources/application.properties
new file mode 100644
index 0000000000..73989eb473
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/main/resources/application.properties
@@ -0,0 +1,21 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#
+# Quarkus
+#
+quarkus.banner.enabled     = false
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackIT.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackIT.java
new file mode 100644
index 0000000000..31ba970ed9
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class RuntimeCustomizerFallbackIT extends RuntimeCustomizerFallbackTest {
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackTest.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackTest.java
new file mode 100644
index 0000000000..6e8025f76f
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerFallbackTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.restassured.path.json.JsonPath;
+import jakarta.ws.rs.core.MediaType;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/5235")
+//@TestProfile(RuntimeCustomizerFallbackTest.Profile.class)
+//@QuarkusTest
+public class RuntimeCustomizerFallbackTest {
+    @Test
+    public void testContextCustomizerFromPropertiesFallback() {
+        JsonPath p = given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/inspect/context")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getBoolean("message-history")).isFalse();
+        assertThat(p.getBoolean("load-type-converters")).isFalse();
+    }
+
+    public static class Profile implements QuarkusTestProfile {
+        @Override
+        public Map<String, String> getConfigOverrides() {
+            return mapOf(
+                    "customizer.test.enabled", "true",
+                    "customizer.test.message-history", "false");
+        }
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerIT.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerIT.java
new file mode 100644
index 0000000000..991bc91f56
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class RuntimeCustomizerIT extends RuntimeCustomizerTest {
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerTest.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerTest.java
new file mode 100644
index 0000000000..6560a9f224
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeCustomizerTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.restassured.path.json.JsonPath;
+import jakarta.ws.rs.core.MediaType;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Disabled("https://github.com/apache/camel-quarkus/issues/5235")
+//@TestProfile(RuntimeCustomizerTest.Profile.class)
+//@QuarkusTest
+public class RuntimeCustomizerTest {
+    @Test
+    public void testContextCustomizerFromProperties() {
+        JsonPath p = given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/inspect/context")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getBoolean("message-history")).isFalse();
+        assertThat(p.getBoolean("load-type-converters")).isFalse();
+    }
+
+    public static class Profile implements QuarkusTestProfile {
+        @Override
+        public Map<String, String> getConfigOverrides() {
+            return mapOf(
+                    "camel.k.customizer.test.enabled", "true",
+                    "camel.k.customizer.test.message-history", "false");
+        }
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeIT.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeIT.java
new file mode 100644
index 0000000000..406cb104c0
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class RuntimeIT extends RuntimeTest {
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeTest.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeTest.java
new file mode 100644
index 0000000000..c5eee3df86
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.path.json.JsonPath;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.quarkus.core.FastCamelContext;
+import org.apache.camel.quarkus.k.runtime.Application;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.is;
+
+@QuarkusTest
+public class RuntimeTest {
+    @Test
+    public void inspect() {
+        JsonPath p = given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/inspect")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getString("camel-context"))
+                .isEqualTo(FastCamelContext.class.getName());
+        assertThat(p.getString("camel-k-runtime"))
+                .isEqualTo(Application.Runtime.class.getName());
+        assertThat(p.getString("routes-collector"))
+                .isEqualTo(Application.NoRoutesCollector.class.getName());
+    }
+
+    @Test
+    public void properties() {
+        given().get("/camel-k/property/my-property").then().statusCode(200).body(is("my-test-value"));
+        given().get("/camel-k/property/root.key").then().statusCode(200).body(is("root.value"));
+        given().get("/camel-k/property/001.key").then().statusCode(200).body(is("001.value"));
+        given().get("/camel-k/property/002.key").then().statusCode(200).body(is("002.value"));
+        given().get("/camel-k/property/a.key").then().statusCode(200).body(is("a.002"));
+        given().get("/camel-k/property/flat-property").then().statusCode(200).body(is("flat-value"));
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlIT.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlIT.java
new file mode 100644
index 0000000000..8f0104b2fa
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class RuntimeWithXmlIT extends RuntimeWithXmlTest {
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlTest.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlTest.java
new file mode 100644
index 0000000000..b66a9eeb64
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithXmlTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.nio.file.Paths;
+import java.util.Map;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.path.json.JsonPath;
+import jakarta.ws.rs.core.MediaType;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@QuarkusTest
+@QuarkusTestResource(RuntimeWithXmlTest.Resources.class)
+public class RuntimeWithXmlTest {
+    @Test
+    public void inspect() {
+        JsonPath p = RestAssured.given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/runtime/inspect")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath();
+
+        assertThat(p.getList("route-definitions", String.class))
+                .contains("xml-simple-route", "xml-route-with-expression", "xml-greetings");
+        assertThat(p.getList("rest-definitions", String.class))
+                .contains("xml-rest-greetings");
+    }
+
+    public static class Resources implements QuarkusTestResourceLifecycleManager {
+        @Override
+        public Map<String, String> start() {
+            final String res = Paths.get("src/test/resources").toAbsolutePath().toString();
+
+            return mapOf(
+                    // sources
+                    "camel.k.sources[0].location", "file:" + res + "/routes.xml",
+                    "camel.k.sources[0].type", "source",
+                    "camel.k.sources[1].location", "file:" + res + "/rests.xml",
+                    "camel.k.sources[1].type", "source",
+                    "camel.k.sources[2].location", "file:" + res + "/routes-with-expression.xml",
+                    "camel.k.sources[2].type", "source",
+                    // misc
+                    "the.body", "10");
+        }
+
+        @Override
+        public void stop() {
+        }
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlIT.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlIT.java
new file mode 100644
index 0000000000..3ab937dd9b
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlIT.java
@@ -0,0 +1,23 @@
+/*
+ * 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.quarkus.k.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class RuntimeWithYamlIT extends RuntimeWithYamlTest {
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlTest.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlTest.java
new file mode 100644
index 0000000000..4d28259a54
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/RuntimeWithYamlTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.quarkus.k.it;
+
+import java.nio.file.Paths;
+import java.util.Map;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.ws.rs.core.MediaType;
+import org.apache.camel.quarkus.k.it.yaml.MyProcessor;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.is;
+
+@QuarkusTest
+@QuarkusTestResource(RuntimeWithYamlTest.Resources.class)
+public class RuntimeWithYamlTest {
+    @Test
+    public void inspect() {
+        given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/runtime/inspect")
+                .then()
+                .statusCode(200)
+                .body("route-definitions", hasItem("my-yaml-route"));
+
+        given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/runtime/registry/beans/my-bean")
+                .then()
+                .statusCode(200)
+                .body("name", is("my-bean-name"));
+
+        given()
+                .accept(MediaType.APPLICATION_JSON)
+                .get("/camel-k/runtime/registry/beans/myProcessor")
+                .then()
+                .statusCode(200);
+    }
+
+    public static class Resources implements QuarkusTestResourceLifecycleManager {
+        @Override
+        public Map<String, String> start() {
+            final String res = Paths.get("src/test/resources").toAbsolutePath().toString();
+
+            return mapOf(
+                    // sources
+                    "camel.k.sources[3].location", "file:" + res + "/routes-with-beans.yaml",
+                    "camel.k.sources[3].type", "source",
+                    // misc
+                    "camel.beans.myProcessor", "#class:" + MyProcessor.class.getName());
+        }
+
+        @Override
+        public void stop() {
+        }
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/TestCustomizer.java b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/TestCustomizer.java
new file mode 100644
index 0000000000..c02e079756
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/java/org/apache/camel/quarkus/k/it/TestCustomizer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.quarkus.k.it;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.engine.ExplicitCamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextCustomizer;
+
+public class TestCustomizer implements CamelContextCustomizer {
+
+    private String name;
+    private boolean messageHistory = true;
+
+    public TestCustomizer() {
+        this("default");
+    }
+
+    public TestCustomizer(String name) {
+        this.name = name;
+    }
+
+    public boolean isMessageHistory() {
+        return messageHistory;
+    }
+
+    public void setMessageHistory(boolean messageHistory) {
+        this.messageHistory = messageHistory;
+    }
+
+    @Override
+    public void configure(CamelContext camelContext) {
+        camelContext.setNameStrategy(new ExplicitCamelContextNameStrategy(name));
+        camelContext.setMessageHistory(messageHistory);
+        camelContext.setLoadTypeConverters(false);
+    }
+}
diff --git a/integration-tests/camel-k-runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/test b/integration-tests/camel-k-runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/test
new file mode 100644
index 0000000000..ea826819d6
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/META-INF/services/org.apache.camel.quarkus.k/customizer/test
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.quarkus.k.it.TestCustomizer
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/conf.d/001/conf.properties b/integration-tests/camel-k-runtime/src/test/resources/conf.d/001/conf.properties
new file mode 100644
index 0000000000..8479286073
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/conf.d/001/conf.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+001.key = 001.value
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/conf.d/002/conf.properties b/integration-tests/camel-k-runtime/src/test/resources/conf.d/002/conf.properties
new file mode 100644
index 0000000000..3ddea2bdbe
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/conf.d/002/conf.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+002.key = 002.value
+a.key = a.002
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/conf.d/003/flat-property b/integration-tests/camel-k-runtime/src/test/resources/conf.d/003/flat-property
new file mode 100644
index 0000000000..313b57de3e
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/conf.d/003/flat-property
@@ -0,0 +1 @@
+flat-value
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/conf.properties b/integration-tests/camel-k-runtime/src/test/resources/conf.properties
new file mode 100644
index 0000000000..9b09020aa9
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/conf.properties
@@ -0,0 +1,21 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+root.key = root.value
+a.key = a.root
+
+my-property = my-test-value
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/rests.xml b/integration-tests/camel-k-runtime/src/test/resources/rests.xml
new file mode 100644
index 0000000000..272d106018
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/rests.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    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.
+
+-->
+<rests xmlns="http://camel.apache.org/schema/spring">
+  <rest path="/camel/" id="xml-rest-greetings">
+    <get id="xml-greetings" path="/greetings/{name}">
+      <param dataType="string" name="name" required="true" type="path"/>
+      <to uri="direct:greeting-api"/>
+    </get>
+  </rest>
+</rests>
diff --git a/integration-tests/camel-k-runtime/src/test/resources/routes-with-beans.yaml b/integration-tests/camel-k-runtime/src/test/resources/routes-with-beans.yaml
new file mode 100644
index 0000000000..fb2a8012c8
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/routes-with-beans.yaml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+- beans:
+    - name: my-bean
+      type: org.apache.camel.quarkus.k.it.yaml.MyBean
+      properties:
+        name: "my-bean-name"
+- route:
+    id: "my-yaml-route"
+    from:
+      uri: "direct:start"
+      steps:
+        - bean:
+            ref: "my-bean"
+            method: "getName"
+        - to: "log:info"
diff --git a/integration-tests/camel-k-runtime/src/test/resources/routes-with-expression.xml b/integration-tests/camel-k-runtime/src/test/resources/routes-with-expression.xml
new file mode 100644
index 0000000000..b3fe307470
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/routes-with-expression.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+  <route id="xml-route-with-expression">
+    <from uri="timer:tick"/>
+    <filter>
+      <simple>${in.body} == {{the.body}}</simple>
+      <to uri="log:info"/>
+    </filter>
+  </route>
+</routes>
\ No newline at end of file
diff --git a/integration-tests/camel-k-runtime/src/test/resources/routes.xml b/integration-tests/camel-k-runtime/src/test/resources/routes.xml
new file mode 100644
index 0000000000..0a0dca729b
--- /dev/null
+++ b/integration-tests/camel-k-runtime/src/test/resources/routes.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+  <route id="xml-simple-route">
+    <from uri="timer:tick"/>
+    <to uri="log:info"/>
+  </route>
+</routes>
\ No newline at end of file
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 8dfaa18633..f2c9f8eb97 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -69,6 +69,7 @@
         <module>box</module>
         <module>braintree</module>
         <module>caffeine</module>
+        <module>camel-k-runtime</module>
         <module>cassandraql</module>
         <module>cbor</module>
         <module>compression-grouped</module>
diff --git a/pom.xml b/pom.xml
index 7ed9e260c4..7ccd556c12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -110,11 +110,13 @@
         <httpclient5.version>${httpclient-version}</httpclient5.version><!-- Saxon and Wiremock -->
         <ibm.mq.client.version>9.3.2.1</ibm.mq.client.version>
         <icu4j.version>${icu4j-version}</icu4j.version>
+        <immutables.version>2.9.3</immutables.version>
         <influxdb.version>${influx-java-driver-version}</influxdb.version>
         <jackson.version>2.15.2</jackson.version><!-- @sync io.quarkus:quarkus-bom:${quarkus.version} dep:com.fasterxml.jackson.core:jackson-core -->
         <jakarta.jms-api.version>${jakarta-jms-api-version}</jakarta.jms-api.version>
         <java-json-tools.json-patch.version>${json-patch-version}</java-json-tools.json-patch.version><!-- A replacement for com.github.fge:json-patch -->
         <jodatime.version>${jodatime2-version}</jodatime.version><!-- Mess in transitive dependencies of Splunk -->
+        <jolokia.version>1.7.2</jolokia.version><!-- For camel-k -->
         <jaxen.version>1.2.0</jaxen.version>
         <javassist.version>${javassist-version}</javassist.version><!-- debezium -->
         <jetty.version>${jetty-version}</jetty.version>
@@ -572,6 +574,7 @@
                             <exclude>node/**</exclude>
                             <exclude>**/resources/routes.1</exclude>
                             <exclude>**/resources/routes.2</exclude>
+                            <exclude>**/conf.d/**</exclude>
                             <exclude>**/generated/**</exclude>
                             <exclude>.envrc</exclude>
                             <exclude>**/.idea/**</exclude>
@@ -579,6 +582,7 @@
                             <exclude>.gitattributes</exclude>
                             <exclude>**/src/test/resources/__files/*.xml</exclude>
                             <exclude>.github/actions/**</exclude>
+                            <exclude>**/my-property</exclude>
                         </excludes>
                         <mapping>
                             <cli>CAMEL_PROPERTIES_STYLE</cli>
diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml
index 49c39287c0..53cb86b53f 100644
--- a/poms/bom-test/pom.xml
+++ b/poms/bom-test/pom.xml
@@ -127,6 +127,16 @@
                 <artifactId>camel-quarkus-integration-tests-support-azure</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-integration-test-support-camel-k-loader-inspector</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-integration-test-support-camel-k-runtime-inspector</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
                 <artifactId>camel-quarkus-integration-tests-support-jdbc</artifactId>
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index 2c042826cf..6c7e0fe370 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -3157,6 +3157,16 @@
                 <artifactId>camel-quarkus-caffeine-deployment</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-deployment</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
                 <artifactId>camel-quarkus-cassandraql</artifactId>
@@ -3839,12 +3849,12 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
-                <artifactId>camel-quarkus-grpc-deployment</artifactId>
+                <artifactId>camel-quarkus-grpc-codegen</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
-                <artifactId>camel-quarkus-grpc-codegen</artifactId>
+                <artifactId>camel-quarkus-grpc-deployment</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
             <dependency>
@@ -6453,6 +6463,31 @@
                 <artifactId>avro-ipc-netty</artifactId>
                 <version>${avro.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.groovy</groupId>
+                <artifactId>groovy</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.groovy</groupId>
+                <artifactId>groovy-json</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.groovy</groupId>
+                <artifactId>groovy-test</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.groovy</groupId>
+                <artifactId>groovy-xml</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.groovy</groupId>
+                <artifactId>groovy-yaml</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.httpcomponents.client5</groupId>
                 <artifactId>httpclient5</artifactId>
@@ -6614,6 +6649,21 @@
                 <artifactId>kotlin-scripting-jvm-host</artifactId>
                 <version>${kotlin.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.jolokia</groupId>
+                <artifactId>jolokia-jvm</artifactId>
+                <version>${jolokia.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.jolokia</groupId>
+                        <artifactId>jolokia-core</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>com.googlecode.json-simple</groupId>
+                        <artifactId>json-simple</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
             <dependency>
                 <groupId>org.mapstruct</groupId>
                 <artifactId>mapstruct-processor</artifactId>
diff --git a/poms/bom/src/main/generated/flattened-full-pom.xml b/poms/bom/src/main/generated/flattened-full-pom.xml
index bbe5aee3bf..0b54a5a059 100644
--- a/poms/bom/src/main/generated/flattened-full-pom.xml
+++ b/poms/bom/src/main/generated/flattened-full-pom.xml
@@ -3083,6 +3083,16 @@
         <artifactId>camel-quarkus-caffeine-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-camel-k</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-camel-k-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-cassandraql</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -3765,12 +3775,12 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
-        <artifactId>camel-quarkus-grpc-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-grpc-codegen</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
-        <artifactId>camel-quarkus-grpc-codegen</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-grpc-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
       <dependency>
@@ -6376,6 +6386,31 @@
         <artifactId>avro-ipc-netty</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>1.11.1</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy-json</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy-test</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy-xml</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy-yaml</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.httpcomponents.client5</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>httpclient5</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -6537,6 +6572,21 @@
         <artifactId>kotlin-scripting-jvm-host</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>1.8.22</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.jolokia</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>jolokia-jvm</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>1.7.2</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <exclusions>
+          <exclusion>
+            <groupId>org.jolokia</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+            <artifactId>jolokia-core</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+          </exclusion>
+          <exclusion>
+            <groupId>com.googlecode.json-simple</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+            <artifactId>json-simple</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+          </exclusion>
+        </exclusions>
+      </dependency>
       <dependency>
         <groupId>org.mapstruct</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>mapstruct-processor</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -7162,11 +7212,6 @@
         <artifactId>cxf-tools-wsdlto-frontend-jaxws</artifactId><!-- io.quarkiverse.cxf:quarkus-cxf-bom:2.2.2 -->
         <version>4.0.2</version><!-- io.quarkiverse.cxf:quarkus-cxf-bom:2.2.2 -->
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
       <dependency>
         <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <artifactId>groovy-ant</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
@@ -7232,11 +7277,6 @@
         <artifactId>groovy-jmx</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy-json</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
       <dependency>
         <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <artifactId>groovy-jsr223</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
@@ -7277,11 +7317,6 @@
         <artifactId>groovy-templates</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy-test</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
       <dependency>
         <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <artifactId>groovy-test-junit5</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
@@ -7302,16 +7337,6 @@
         <artifactId>groovy-typecheckers</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
         <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy-xml</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy-yaml</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
       <dependency>
         <groupId>software.amazon.awssdk</groupId><!-- software.amazon.awssdk:bom:2.20.128 -->
         <artifactId>codegen-lite-maven-plugin</artifactId><!-- software.amazon.awssdk:bom:2.20.128 -->
diff --git a/poms/bom/src/main/generated/flattened-reduced-pom.xml b/poms/bom/src/main/generated/flattened-reduced-pom.xml
index ba990f9f76..1388418cd2 100644
--- a/poms/bom/src/main/generated/flattened-reduced-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-pom.xml
@@ -3083,6 +3083,16 @@
         <artifactId>camel-quarkus-caffeine-deployment</artifactId>
         <version>3.3.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-camel-k</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-camel-k-deployment</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId>
         <artifactId>camel-quarkus-cassandraql</artifactId>
@@ -3765,12 +3775,12 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-grpc-deployment</artifactId>
+        <artifactId>camel-quarkus-grpc-codegen</artifactId>
         <version>3.3.0-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-grpc-codegen</artifactId>
+        <artifactId>camel-quarkus-grpc-deployment</artifactId>
         <version>3.3.0-SNAPSHOT</version>
       </dependency>
       <dependency>
@@ -6351,6 +6361,11 @@
         <artifactId>antlr-runtime</artifactId>
         <version>3.5.2</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId>
+        <artifactId>groovy</artifactId>
+        <version>4.0.13</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.httpcomponents.client5</groupId>
         <artifactId>httpclient5</artifactId>
@@ -7107,11 +7122,6 @@
         <artifactId>cxf-tools-wsdlto-frontend-jaxws</artifactId>
         <version>4.0.2</version>
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId>
-        <artifactId>groovy</artifactId>
-        <version>4.0.13</version>
-      </dependency>
       <dependency>
         <groupId>software.amazon.awssdk</groupId>
         <artifactId>annotations</artifactId>
diff --git a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
index 4c8e4b484c..802f4e42d4 100644
--- a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
@@ -3083,6 +3083,16 @@
         <artifactId>camel-quarkus-caffeine-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-camel-k</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-camel-k-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-cassandraql</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -3765,12 +3775,12 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
-        <artifactId>camel-quarkus-grpc-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-grpc-codegen</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
-        <artifactId>camel-quarkus-grpc-codegen</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-grpc-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.3.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
       <dependency>
@@ -6351,6 +6361,11 @@
         <artifactId>antlr-runtime</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>3.5.2</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
+      <dependency>
+        <groupId>org.apache.groovy</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>groovy</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>4.0.13</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
       <dependency>
         <groupId>org.apache.httpcomponents.client5</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>httpclient5</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
@@ -7107,11 +7122,6 @@
         <artifactId>cxf-tools-wsdlto-frontend-jaxws</artifactId><!-- io.quarkiverse.cxf:quarkus-cxf-bom:2.2.2 -->
         <version>4.0.2</version><!-- io.quarkiverse.cxf:quarkus-cxf-bom:2.2.2 -->
       </dependency>
-      <dependency>
-        <groupId>org.apache.groovy</groupId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <artifactId>groovy</artifactId><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-        <version>4.0.13</version><!-- org.apache.groovy:groovy-bom:4.0.13 -->
-      </dependency>
       <dependency>
         <groupId>software.amazon.awssdk</groupId><!-- software.amazon.awssdk:bom:2.20.128 -->
         <artifactId>annotations</artifactId><!-- software.amazon.awssdk:bom:2.20.128 -->
diff --git a/tooling/camel-k-catalog-model/pom.xml b/tooling/camel-k-catalog-model/pom.xml
new file mode 100644
index 0000000000..d65af2f0a2
--- /dev/null
+++ b/tooling/camel-k-catalog-model/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-camel-k-catalog-model</artifactId>
+    <name>Camel Quarkus :: Tooling :: Camel K Catalog Model</name>
+    <description>Model classes specific to Camel K Maven Plugin to generate the Camel K Catalog.</description>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-bom</artifactId>
+                <version>${quarkus.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.immutables</groupId>
+                <artifactId>value</artifactId>
+                <version>${immutables.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jdk8</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>value</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/Artifact.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/Artifact.java
new file mode 100644
index 0000000000..dde1b0910a
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/Artifact.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.quarkus.k.catalog.model;
+
+import java.util.Comparator;
+import java.util.Optional;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonPropertyOrder({ "groupId", "artifactId", "version" })
+public interface Artifact extends Comparable<Artifact> {
+    String getGroupId();;
+
+    String getArtifactId();
+
+    Optional<String> getVersion();
+
+    @Override
+    default int compareTo(Artifact o) {
+        return Comparator
+                .comparing(Artifact::getGroupId)
+                .thenComparing(Artifact::getArtifactId)
+                .thenComparing(Artifact::getVersion, Comparator.comparing(c -> c.orElse("")))
+                .compare(this, o);
+    }
+
+    static Artifact from(String groupId, String artifactId) {
+        return new Artifact() {
+            @Override
+            public String getGroupId() {
+                return groupId;
+            }
+
+            @Override
+            public String getArtifactId() {
+                return artifactId;
+            }
+
+            @Override
+            public Optional<String> getVersion() {
+                return Optional.empty();
+            }
+        };
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelArtifact.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelArtifact.java
new file mode 100644
index 0000000000..4bf59316d6
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelArtifact.java
@@ -0,0 +1,82 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import java.util.Collections;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = CamelArtifact.Builder.class)
+@JsonPropertyOrder({ "groupId", "artifactId", "version" })
+public interface CamelArtifact extends Artifact {
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<CamelScheme> getSchemes() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getLanguages() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getDataformats() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getDependencies() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getExclusions() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getJavaTypes() {
+        return Collections.emptySortedSet();
+    }
+
+    static Builder from(String groupId, String artifactId) {
+        return new Builder().groupId(groupId).artifactId(artifactId);
+    }
+
+    class Builder extends ImmutableCamelArtifact.Builder {
+        public Builder addDependency(String groupId, String artifactId) {
+            return super.addDependencies(Artifact.from(groupId, artifactId));
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelCapability.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelCapability.java
new file mode 100644
index 0000000000..3b5485285c
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelCapability.java
@@ -0,0 +1,47 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import java.util.Collections;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = CamelCapability.Builder.class)
+@JsonPropertyOrder({ "groupId", "artifactId", "version" })
+public interface CamelCapability {
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getDependencies() {
+        return Collections.emptySortedSet();
+    }
+
+    static CamelCapability forArtifact(String groupId, String artifactId) {
+        return new Builder().addDependency(groupId, artifactId).build();
+    }
+
+    class Builder extends ImmutableCamelCapability.Builder {
+        public Builder addDependency(String groupId, String artifactId) {
+            return super.addDependencies(Artifact.from(groupId, artifactId));
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelLoader.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelLoader.java
new file mode 100644
index 0000000000..de952e3c66
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelLoader.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.quarkus.k.catalog.model;
+
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = CamelLoader.Builder.class)
+@JsonPropertyOrder({ "groupId", "artifactId", "version" })
+public interface CamelLoader extends Artifact {
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getLanguages() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getDependencies() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, String> getMetadata() {
+        return Collections.emptySortedMap();
+    }
+
+    static Builder fromArtifact(String groupId, String artifactId) {
+        return new Builder().groupId(groupId).artifactId(artifactId);
+    }
+
+    class Builder extends ImmutableCamelLoader.Builder {
+        public Builder addDependency(String groupId, String artifactId) {
+            return super.addDependencies(Artifact.from(groupId, artifactId));
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScheme.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScheme.java
new file mode 100644
index 0000000000..a133e6f1bf
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScheme.java
@@ -0,0 +1,66 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Optional;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@JsonDeserialize(builder = CamelScheme.Builder.class)
+public interface CamelScheme extends Comparable<CamelScheme> {
+    String getId();
+
+    @Value.Auxiliary
+    @Value.Default
+    default boolean http() {
+        return false;
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    default boolean passive() {
+        return false;
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getRequiredCapabilities() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    Optional<CamelScopedArtifact> getProducer();
+
+    @Value.Auxiliary
+    Optional<CamelScopedArtifact> getConsumer();
+
+    @Override
+    default int compareTo(CamelScheme o) {
+        return Comparator
+                .comparing(CamelScheme::getId)
+                .compare(this, o);
+    }
+
+    class Builder extends ImmutableCamelScheme.Builder {
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScopedArtifact.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScopedArtifact.java
new file mode 100644
index 0000000000..6960eb8a1b
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CamelScopedArtifact.java
@@ -0,0 +1,50 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import java.util.Collections;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = CamelScopedArtifact.Builder.class)
+@JsonPropertyOrder({ "dependencies", "required-capabilities" })
+public interface CamelScopedArtifact {
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getDependencies() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Auxiliary
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<String> getRequiredCapabilities() {
+        return Collections.emptySortedSet();
+    }
+
+    class Builder extends ImmutableCamelScopedArtifact.Builder {
+        public Builder addDependency(String groupId, String artifactId) {
+            return super.addDependencies(Artifact.from(groupId, artifactId));
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogComponentDefinition.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogComponentDefinition.java
new file mode 100644
index 0000000000..94ec1fcd11
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogComponentDefinition.java
@@ -0,0 +1,80 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import java.util.stream.Stream;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.camel.util.StringHelper;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class CatalogComponentDefinition extends CatalogDefinition {
+    private String scheme;
+    private String alternativeSchemes;
+    private String javaType;
+
+    public Stream<String> getSchemes() {
+        final String schemeIDs = StringHelper.trimToNull(alternativeSchemes);
+
+        return schemeIDs == null
+                ? Stream.of(scheme)
+                : Stream.concat(
+                        Stream.of(scheme),
+                        StringHelper.splitAsStream(schemeIDs, ","));
+    }
+
+    public String getScheme() {
+        return scheme;
+    }
+
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+
+    public String getAlternativeSchemes() {
+        return alternativeSchemes;
+    }
+
+    public void setAlternativeSchemes(String alternativeSchemes) {
+        this.alternativeSchemes = alternativeSchemes;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static final class Container {
+        private final CatalogComponentDefinition delegate;
+
+        @JsonCreator
+        public Container(
+                @JsonProperty("component") CatalogComponentDefinition delegate) {
+            this.delegate = delegate;
+        }
+
+        public CatalogComponentDefinition unwrap() {
+            return delegate;
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDataFormatDefinition.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDataFormatDefinition.java
new file mode 100644
index 0000000000..16f0a284d9
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDataFormatDefinition.java
@@ -0,0 +1,58 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class CatalogDataFormatDefinition extends CatalogDefinition {
+    private String name;
+    private String javaType;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static final class Container {
+        private final CatalogDataFormatDefinition delegate;
+
+        @JsonCreator
+        public Container(
+                @JsonProperty("dataformat") CatalogDataFormatDefinition delegate) {
+            this.delegate = delegate;
+        }
+
+        public CatalogDataFormatDefinition unwrap() {
+            return delegate;
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDefinition.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDefinition.java
new file mode 100644
index 0000000000..841d393e3d
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogDefinition.java
@@ -0,0 +1,47 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+public class CatalogDefinition {
+    private String groupId;
+    private String artifactId;
+    private String version;
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogLanguageDefinition.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogLanguageDefinition.java
new file mode 100644
index 0000000000..44240711ec
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogLanguageDefinition.java
@@ -0,0 +1,58 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class CatalogLanguageDefinition extends CatalogDefinition {
+    private String name;
+    private String javaType;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static final class Container {
+        private final CatalogLanguageDefinition delegate;
+
+        @JsonCreator
+        public Container(
+                @JsonProperty("language") CatalogLanguageDefinition delegate) {
+            this.delegate = delegate;
+        }
+
+        public CatalogLanguageDefinition unwrap() {
+            return delegate;
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogOtherDefinition.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogOtherDefinition.java
new file mode 100644
index 0000000000..69e658f0d5
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogOtherDefinition.java
@@ -0,0 +1,49 @@
+/*
+ * 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.quarkus.k.catalog.model;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public final class CatalogOtherDefinition extends CatalogDefinition {
+    private String label;
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    public static final class Container {
+        private final CatalogOtherDefinition delegate;
+
+        @JsonCreator
+        public Container(
+                @JsonProperty("other") CatalogOtherDefinition delegate) {
+            this.delegate = delegate;
+        }
+
+        public CatalogOtherDefinition unwrap() {
+            return delegate;
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogSupport.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogSupport.java
new file mode 100644
index 0000000000..ea8ebe32c0
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/CatalogSupport.java
@@ -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.
+ */
+package org.apache.camel.quarkus.k.catalog.model;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public final class CatalogSupport {
+
+    private CatalogSupport() {
+    }
+
+    private static <T> T unmarshall(String json, Class<T> type) {
+        try {
+            return new ObjectMapper().readValue(json, type);
+        } catch (IOException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public static CatalogComponentDefinition unmarshallComponent(String json) {
+        return unmarshall(json, CatalogComponentDefinition.Container.class).unwrap();
+    }
+
+    public static CatalogLanguageDefinition unmarshallLanguage(String json) {
+        return unmarshall(json, CatalogLanguageDefinition.Container.class).unwrap();
+    }
+
+    public static CatalogDataFormatDefinition unmarshallDataFormat(String json) {
+        return unmarshall(json, CatalogDataFormatDefinition.Container.class).unwrap();
+    }
+
+    public static CatalogOtherDefinition unmarshallOther(String json) {
+        return unmarshall(json, CatalogOtherDefinition.Container.class).unwrap();
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/ObjectMeta.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/ObjectMeta.java
new file mode 100644
index 0000000000..5ee5b63e38
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/ObjectMeta.java
@@ -0,0 +1,38 @@
+/*
+ * 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.quarkus.k.catalog.model.k8s;
+
+import java.util.Collections;
+import java.util.SortedMap;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@JsonDeserialize(builder = ObjectMeta.Builder.class)
+public interface ObjectMeta {
+    String getName();
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, String> getLabels() {
+        return Collections.emptySortedMap();
+    }
+
+    class Builder extends ImmutableObjectMeta.Builder {
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/TypeMeta.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/TypeMeta.java
new file mode 100644
index 0000000000..eca7a41213
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/TypeMeta.java
@@ -0,0 +1,37 @@
+/*
+ * 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.quarkus.k.catalog.model.k8s;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@JsonDeserialize(builder = TypeMeta.Builder.class)
+public interface TypeMeta {
+    @Value.Default
+    default String getApiVersion() {
+        return "camel.apache.org/v1";
+    }
+
+    @Value.Default
+    default String getKind() {
+        return "CamelCatalog";
+    }
+
+    class Builder extends ImmutableTypeMeta.Builder {
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalog.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalog.java
new file mode 100644
index 0000000000..8747c81098
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalog.java
@@ -0,0 +1,44 @@
+/*
+ * 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.quarkus.k.catalog.model.k8s.crd;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.camel.quarkus.k.catalog.model.k8s.ObjectMeta;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@JsonDeserialize(builder = CamelCatalog.Builder.class)
+@JsonPropertyOrder({ "apiVersion", "kind", "metadata", "spec" })
+public interface CamelCatalog {
+    @Value.Default
+    default String getApiVersion() {
+        return "camel.apache.org/v1";
+    }
+
+    @Value.Default
+    default String getKind() {
+        return "CamelCatalog";
+    }
+
+    ObjectMeta getMetadata();
+
+    CamelCatalogSpec getSpec();
+
+    class Builder extends ImmutableCamelCatalog.Builder {
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalogSpec.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalogSpec.java
new file mode 100644
index 0000000000..e36019947b
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/CamelCatalogSpec.java
@@ -0,0 +1,56 @@
+/*
+ * 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.quarkus.k.catalog.model.k8s.crd;
+
+import java.util.Collections;
+import java.util.SortedMap;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.camel.quarkus.k.catalog.model.CamelArtifact;
+import org.apache.camel.quarkus.k.catalog.model.CamelLoader;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = CamelCatalogSpec.Builder.class)
+@JsonPropertyOrder({ "runtime", "artifacts" })
+public interface CamelCatalogSpec {
+    RuntimeSpec getRuntime();
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, CamelArtifact> getArtifacts() {
+        return Collections.emptySortedMap();
+    }
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, CamelLoader> getLoaders() {
+        return Collections.emptySortedMap();
+    }
+
+    class Builder extends ImmutableCamelCatalogSpec.Builder {
+        public Builder putArtifact(CamelArtifact artifact) {
+            return putArtifact(artifact.getArtifactId(), artifact);
+        }
+
+        public Builder putArtifact(String groupId, String artifactId) {
+            return putArtifact(new CamelArtifact.Builder().groupId(groupId).artifactId(artifactId).build());
+        }
+    }
+}
diff --git a/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/RuntimeSpec.java b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/RuntimeSpec.java
new file mode 100644
index 0000000000..22c22ab62c
--- /dev/null
+++ b/tooling/camel-k-catalog-model/src/main/java/org/apache/camel/quarkus/k/catalog/model/k8s/crd/RuntimeSpec.java
@@ -0,0 +1,63 @@
+/*
+ * 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.quarkus.k.catalog.model.k8s.crd;
+
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.camel.quarkus.k.catalog.model.Artifact;
+import org.apache.camel.quarkus.k.catalog.model.CamelCapability;
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(depluralize = true)
+@JsonDeserialize(builder = RuntimeSpec.Builder.class)
+@JsonPropertyOrder({ "version", "runtimeVersion", "artifacts" })
+public interface RuntimeSpec {
+    String getProvider();
+
+    String getVersion();
+
+    String getApplicationClass();
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, String> getMetadata() {
+        return Collections.emptySortedMap();
+    }
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedSet<Artifact> getDependencies() {
+        return Collections.emptySortedSet();
+    }
+
+    @Value.Default
+    @Value.NaturalOrder
+    default SortedMap<String, CamelCapability> getCapabilities() {
+        return Collections.emptySortedMap();
+    }
+
+    class Builder extends ImmutableRuntimeSpec.Builder {
+        public Builder addDependency(String groupId, String artifactId) {
+            return super.addDependencies(Artifact.from(groupId, artifactId));
+        }
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/pom.xml b/tooling/camel-k-maven-plugin/pom.xml
new file mode 100644
index 0000000000..6abbc2b9e2
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/pom.xml
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent</artifactId>
+        <version>3.3.0-SNAPSHOT</version>
+        <relativePath>../../poms/build-parent/pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+    <name>Camel Quarkus :: Tooling :: Camel K Maven Plugin</name>
+    <description>Maven plugin to generate the catalog of artifacts specific to Camel K.</description>
+    <packaging>maven-plugin</packaging>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-bom</artifactId>
+                <version>${quarkus.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-catalog-model</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-openapi-rest-dsl-generator</artifactId>
+                <version>${camel.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>jsr305</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.inject</groupId>
+                    <artifactId>javax.inject</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.codehaus.plexus</groupId>
+                    <artifactId>plexus-classworlds</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-camel-k-catalog-model</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-openapi-rest-dsl-generator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-catalog</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-catalog</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-catalog</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jdk8</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <configuration>
+                    <mojoDependencies>
+                        <dep>org.apache.maven:maven-plugin-api</dep>
+                    </mojoDependencies>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default-descriptor</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <!-- Sanity checks and formatting are disabled when building with '-Dquickly' -->
+            <id>full</id>
+            <activation>
+                <property>
+                    <name>!quickly</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-invoker-plugin</artifactId>
+                        <configuration>
+                            <scriptVariables>
+                                <camelVersion>${camel.version}</camelVersion>
+                                <camelQuarkusVersion>${project.version}</camelQuarkusVersion>
+                                <quarkusVersion>${quarkus.version}</quarkusVersion>
+                            </scriptVariables>
+                            <pomIncludes>
+                                <pomInclude>generate-catalog/pom.xml</pomInclude>
+                                <pomInclude>generate-catalog-with-exclusions/pom.xml</pomInclude>
+                                <pomInclude>generate-dependencies/pom.xml</pomInclude>
+                                <pomInclude>generate-rest-dsl-from-v2/pom.xml</pomInclude>
+                                <pomInclude>generate-rest-dsl-from-v3/pom.xml</pomInclude>
+                            </pomIncludes>
+                            <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+                            <cloneClean>true</cloneClean>
+                            <postBuildHookScript>verify</postBuildHookScript>
+                            <addTestClassPath>true</addTestClassPath>
+                            <streamLogs>true</streamLogs>
+                            <goals>
+                                <goal>prepare-package</goal>
+                            </goals>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>integration-tests</id>
+                                <goals>
+                                    <goal>install</goal>
+                                    <goal>run</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <properties>
+                                        <com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize>true
+                                        </com.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize>
+                                        <failIfNoTests>false</failIfNoTests>
+                                    </properties>
+                                </configuration>
+                            </execution>
+                        </executions>
+                        <dependencies>
+                            <dependency>
+                                <groupId>org.apache.groovy</groupId>
+                                <artifactId>groovy</artifactId>
+                                <version>${groovy.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.groovy</groupId>
+                                <artifactId>groovy-yaml</artifactId>
+                                <version>${groovy.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.groovy</groupId>
+                                <artifactId>groovy-json</artifactId>
+                                <version>${groovy.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.groovy</groupId>
+                                <artifactId>groovy-xml</artifactId>
+                                <version>${groovy.version}</version>
+                            </dependency>
+                            <dependency>
+                                <groupId>org.apache.commons</groupId>
+                                <artifactId>commons-collections4</artifactId>
+                                <version>${commons-collections4-version}</version>
+                            </dependency>
+                        </dependencies>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+    </profiles>
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/pom.xml b/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/pom.xml
new file mode 100644
index 0000000000..05a73e4463
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.camel.k</groupId>
+    <artifactId>camel-k-catalog-generator</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <catalog.dir>${project.basedir}</catalog.dir>
+        <catalog.runtime>quarkus</catalog.runtime>
+        <catalog.file>catalog.yaml</catalog.file>
+        <!-- exclusion list -->
+        <dsls.exclusion.list>jsh,js,kts,groovy</dsls.exclusion.list>
+        <dataformats.exclusion.list>avro-jackson</dataformats.exclusion.list>
+        <languages.exclusion.list>csimple</languages.exclusion.list>
+        <components.exclusion.list>disruptor,disruptor-vm</components.exclusion.list>
+        <others.exclusion.list>jta,redis</others.exclusion.list>
+        <capabilities.exclusion.list>master</capabilities.exclusion.list>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>generate-catalog</id>
+                        <goals>
+                            <goal>generate-catalog</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+        <pluginRepository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/verify.groovy
new file mode 100644
index 0000000000..53725658e7
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-catalog-with-exclusions/verify.groovy
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+new File(basedir, "catalog.yaml").withReader {
+    def catalog = new groovy.yaml.YamlSlurper().parse(it)
+
+    assert catalog.spec.loaders['jsh'] == null
+    assert catalog.spec.loaders['kts'] == null
+    assert catalog.spec.loaders['js'] == null
+    assert catalog.spec.loaders['groovy'] == null
+
+    assert catalog.spec.loaders['java'] != null
+    assert catalog.spec.loaders['xml'] != null
+    assert catalog.spec.loaders['yaml'] != null
+
+    assert catalog.spec.artifacts['camel-quarkus-jackson-avro'] != null
+    assert catalog.spec.artifacts['camel-quarkus-csimple'] == null
+    assert catalog.spec.artifacts['camel-quarkus-disruptor'] == null
+
+    assert catalog.spec.artifacts['camel-quarkus-debug'] != null
+    assert catalog.spec.artifacts['camel-quarkus-jta'] == null
+    assert catalog.spec.artifacts['camel-quarkus-redis'] == null
+
+    assert catalog.spec.runtime.capabilities['master'] == null
+    assert catalog.spec.artifacts['camel-k-master'] == null
+}
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-catalog/pom.xml b/tooling/camel-k-maven-plugin/src/it/generate-catalog/pom.xml
new file mode 100644
index 0000000000..ef164af6ff
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-catalog/pom.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.camel.k</groupId>
+    <artifactId>camel-k-catalog-generator</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <catalog.dir>${project.basedir}</catalog.dir>
+        <catalog.runtime>quarkus</catalog.runtime>
+        <catalog.file>catalog.yaml</catalog.file>
+        <!-- If needed, components can be excluded with the exclusion.list property -->
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>generate-catalog</id>
+                        <goals>
+                            <goal>generate-catalog</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+        <pluginRepository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-catalog/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-catalog/verify.groovy
new file mode 100644
index 0000000000..43c1d13f2d
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-catalog/verify.groovy
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+new File(basedir, "catalog.yaml").withReader {
+    def catalog = new groovy.yaml.YamlSlurper().parse(it)
+
+    // assert catalog.spec.runtime.version == runtimeVersion
+    assert catalog.spec.runtime.applicationClass == 'io.quarkus.bootstrap.runner.QuarkusEntryPoint'
+    assert catalog.spec.runtime.metadata['camel.version'] == camelVersion
+    // Re-enabled this when the version will be the same again
+    assert catalog.spec.runtime.metadata['quarkus.version'] == quarkusVersion
+    assert catalog.spec.runtime.metadata['camel-quarkus.version'] == camelQuarkusVersion
+    // assert catalog.spec.runtime.metadata['quarkus.native-builder-image'] == quarkusNativeBuilderImage
+
+    assert catalog.spec.runtime.dependencies.any {
+        it.groupId == 'org.apache.camel.quarkus' && it.artifactId == 'camel-quarkus-k-runtime'
+    }
+
+    assert catalog.spec.runtime.capabilities['cron'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['cron'].dependencies[0].artifactId == 'camel-k-cron'
+    assert catalog.spec.runtime.capabilities['health'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['health'].dependencies[0].artifactId == 'camel-quarkus-microprofile-health'
+    assert catalog.spec.runtime.capabilities['rest'].dependencies.any { it.groupId == 'org.apache.camel.quarkus' && it.artifactId == 'camel-quarkus-rest' }
+    assert catalog.spec.runtime.capabilities['rest'].dependencies.any { it.groupId == 'org.apache.camel.quarkus' && it.artifactId == 'camel-quarkus-platform-http' }
+    assert catalog.spec.runtime.capabilities['platform-http'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['platform-http'].dependencies[0].artifactId == 'camel-quarkus-platform-http'
+    assert catalog.spec.runtime.capabilities['circuit-breaker'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['circuit-breaker'].dependencies[0].artifactId == 'camel-quarkus-microprofile-fault-tolerance'
+    assert catalog.spec.runtime.capabilities['tracing'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['tracing'].dependencies[0].artifactId == 'camel-quarkus-opentracing'
+    assert catalog.spec.runtime.capabilities['telemetry'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['telemetry'].dependencies[0].artifactId == 'camel-quarkus-opentelemetry'
+    assert catalog.spec.runtime.capabilities['master'].dependencies[0].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.runtime.capabilities['master'].dependencies[0].artifactId == 'camel-k-master'
+
+    assert catalog.spec.loaders['groovy'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['groovy'].artifactId == 'camel-quarkus-groovy-dsl'
+    assert catalog.spec.loaders['groovy'].languages[0] == 'groovy'
+    assert catalog.spec.loaders['groovy'].metadata['native'] == 'true'
+    assert catalog.spec.loaders['groovy'].metadata['sources-required-at-build-time'] == 'true'
+    assert catalog.spec.loaders['java'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['java'].artifactId == 'camel-quarkus-java-joor-dsl'
+    assert catalog.spec.loaders['java'].languages[0] == 'java'
+    assert catalog.spec.loaders['java'].metadata['native'] == 'true'
+    assert catalog.spec.loaders['java'].metadata['sources-required-at-build-time'] == 'true'
+    assert catalog.spec.loaders['jsh'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['jsh'].artifactId == 'camel-quarkus-jsh-dsl'
+    assert catalog.spec.loaders['jsh'].languages[0] == 'jsh'
+    assert catalog.spec.loaders['jsh'].metadata['native'] == 'false'
+    assert catalog.spec.loaders['jsh'].metadata['sources-required-at-build-time'] == 'true'
+    assert catalog.spec.loaders['kts'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['kts'].artifactId == 'camel-quarkus-kotlin-dsl'
+    assert catalog.spec.loaders['kts'].languages[0] == 'kts'
+    assert catalog.spec.loaders['kts'].metadata['native'] == 'true'
+    assert catalog.spec.loaders['kts'].metadata['sources-required-at-build-time'] == 'true'
+    assert catalog.spec.loaders['js'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['js'].artifactId == 'camel-quarkus-js-dsl'
+    assert catalog.spec.loaders['js'].languages[0] == 'js'
+    assert catalog.spec.loaders['js'].metadata['native'] == 'false'
+    assert catalog.spec.loaders['js'].metadata['sources-required-at-build-time'] == null
+    assert catalog.spec.loaders['xml'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['xml'].artifactId == 'camel-quarkus-xml-io-dsl'
+    assert catalog.spec.loaders['xml'].languages[0] == 'xml'
+    assert catalog.spec.loaders['xml'].metadata['native'] == 'true'
+    assert catalog.spec.loaders['xml'].metadata['sources-required-at-build-time'] == null
+    assert catalog.spec.loaders['yaml'].groupId == 'org.apache.camel.quarkus'
+    assert catalog.spec.loaders['yaml'].artifactId == 'camel-quarkus-yaml-dsl'
+    assert catalog.spec.loaders['yaml'].languages[0] == 'yaml'
+    assert catalog.spec.loaders['yaml'].metadata['native'] == 'true'
+    assert catalog.spec.loaders['yaml'].metadata['sources-required-at-build-time'] == null
+
+    assert catalog.metadata.labels['camel.apache.org/runtime.version'] == camelQuarkusVersion
+
+    catalog.spec.artifacts['camel-k-master'].with {
+        schemes == null
+    }
+    catalog.spec.artifacts['camel-k-cron'].with {
+        schemes == null
+    }
+
+    def diff = org.apache.commons.collections4.CollectionUtils.disjunction(
+            catalog.spec.artifacts.values()
+                    .findAll { it.schemes != null }
+                    .collect { it.schemes.collect { it.id } }
+                    .flatten(),
+            catalog.spec.artifacts.values()
+                    .findAll { it.schemes != null }
+                    .collect { it.schemes.collect { it.id } }
+                    .flatten()
+                    .unique()
+    )
+
+    assert diff.size() == 0 : "Duplicated schemes: ${diff}"
+
+    catalog.spec.artifacts.each { k,v ->
+        assert k != null
+        assert v.groupId != null
+        assert v.artifactId != null
+        assert v.version == null
+    }
+
+    catalog.spec.artifacts['camel-quarkus-knative'].with {
+        assert dependencies == null
+        assert requiredCapabilities == null
+        assert schemes.size() == 1
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-dependencies/pom.xml b/tooling/camel-k-maven-plugin/src/it/generate-dependencies/pom.xml
new file mode 100644
index 0000000000..2e86fee3c4
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-dependencies/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.camel.k</groupId>
+    <artifactId>camel-k-catalog-generator</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <dependencies.file>${project.basedir}/dependencies.yaml</dependencies.file>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.14</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>generate-dependency-list</id>
+                        <goals>
+                            <goal>generate-dependency-list</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+        <pluginRepository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-dependencies/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-dependencies/verify.groovy
new file mode 100644
index 0000000000..465fa68ddf
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-dependencies/verify.groovy
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+import org.apache.commons.codec.digest.DigestUtils
+
+import java.nio.charset.StandardCharsets
+import java.nio.file.Files
+
+new File(basedir, "dependencies.yaml").withReader {
+    def deps = new groovy.yaml.YamlSlurper().parse(it)
+
+    assert deps.dependencies.size() != 0
+
+    for (Map<String, String> dependency: deps.dependencies) {
+        dependency.checksum != null
+        dependency.location != null
+        dependency.id != null
+
+        File checksum
+
+        if ((checksum = new File("${dependency.location}.md5")).exists()) {
+            assert dependency.checksum == "md5:" + Files.readString(checksum.toPath(), StandardCharsets.UTF_8)
+        } else if ((checksum = new File("${dependency.location}.sha1")).exists()) {
+            assert dependency.checksum == "sha1:" + Files.readString(checksum.toPath(), StandardCharsets.UTF_8)
+        } else {
+            def file  = new File(dependency.location)
+            def bytes = Files.readAllBytes(file.toPath())
+
+            assert dependency.checksum == "sha1:" + DigestUtils.sha1Hex(bytes)
+        }
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/document.json b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/document.json
new file mode 100644
index 0000000000..48e8f9e7fd
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/document.json
@@ -0,0 +1,46 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0",
+    "title" : "Greeting REST API"
+  },
+  "host" : "",
+  "basePath" : "/camel/",
+  "tags" : [ {
+    "name" : "greetings",
+    "description" : "Greeting to {name}"
+  } ],
+  "schemes" : [ "http" ],
+  "paths" : {
+    "/greetings/{name}" : {
+      "get" : {
+        "tags" : [ "greetings" ],
+        "operationId" : "greeting-api",
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "path",
+          "required" : true,
+          "type" : "string"
+        } ],
+        "responses" : {
+          "200" : {
+            "description" : "Output type",
+            "schema" : {
+              "$ref" : "#/definitions/Greetings"
+            }
+          }
+        }
+      }
+    }
+  },
+  "definitions" : {
+    "Greetings" : {
+      "type" : "object",
+      "properties" : {
+        "greetings" : {
+          "type" : "string"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/pom.xml b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/pom.xml
new file mode 100644
index 0000000000..2d1e7cd007
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.camel.k</groupId>
+    <artifactId>camel-k-catalog-generator</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <openapi.spec>${project.basedir}/document.json</openapi.spec>
+        <dsl.out>${project.basedir}/document.xml</dsl.out>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>generate-rest-xml</id>
+                        <goals>
+                            <goal>generate-rest-xml</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+        <pluginRepository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/verify.groovy
new file mode 100644
index 0000000000..9dfe128c1f
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v2/verify.groovy
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+
+new File(basedir, "document.xml").withReader {
+    def document = new groovy.util.XmlSlurper().parse(it)
+
+    assert document.rest.@path == '/camel/'
+    assert document.rest.get.size() == 1
+    assert document.rest.get[0].@id == 'greeting-api'
+    assert document.rest.get[0].@path == '/greetings/{name}'
+    assert document.rest.get[0].to.@uri == 'direct:greeting-api'
+}
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/document.yaml b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/document.yaml
new file mode 100644
index 0000000000..7d0d31a214
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/document.yaml
@@ -0,0 +1,128 @@
+#
+# 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.
+#
+
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+  license:
+    name: MIT
+servers:
+  - url: http://petstore.swagger.io/v1
+paths:
+  /pets:
+    get:
+      summary: List all pets
+      operationId: listPets
+      tags:
+        - pets
+      parameters:
+        - name: limit
+          in: query
+          description: How many items to return at one time (max 100)
+          required: false
+          schema:
+            type: integer
+            format: int32
+      responses:
+        '200':
+          description: A paged array of pets
+          headers:
+            x-next:
+              description: A link to the next page of responses
+              schema:
+                type: string
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Pets"
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Error"
+    post:
+      summary: Create a pet
+      operationId: createPets
+      tags:
+        - pets
+      responses:
+        '201':
+          description: Null response
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Error"
+  /pets/{petId}:
+    get:
+      summary: Info for a specific pet
+      operationId: showPetById
+      tags:
+        - pets
+      parameters:
+        - name: petId
+          in: path
+          required: true
+          description: The id of the pet to retrieve
+          schema:
+            type: string
+      responses:
+        '200':
+          description: Expected response to a valid request
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Pet"
+        default:
+          description: unexpected error
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Error"
+components:
+  schemas:
+    Pet:
+      type: object
+      required:
+        - id
+        - name
+      properties:
+        id:
+          type: integer
+          format: int64
+        name:
+          type: string
+        tag:
+          type: string
+    Pets:
+      type: array
+      items:
+        $ref: "#/components/schemas/Pet"
+    Error:
+      type: object
+      required:
+        - code
+        - message
+      properties:
+        code:
+          type: integer
+          format: int32
+        message:
+          type: string
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/pom.xml b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/pom.xml
new file mode 100644
index 0000000000..5ebe40e0a6
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.camel.k</groupId>
+    <artifactId>camel-k-catalog-generator</artifactId>
+    <version>1.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <openapi.spec>${project.basedir}/document.yaml</openapi.spec>
+        <dsl.out>${project.basedir}/document.xml</dsl.out>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-camel-k-maven-plugin</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>generate-rest-xml</id>
+                        <goals>
+                            <goal>generate-rest-xml</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <name>Apache Development Snapshot Repository</name>
+            <url>https://repository.apache.org/content/repositories/snapshots/</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+        <pluginRepository>
+            <id>oss.snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/verify.groovy
new file mode 100644
index 0000000000..6be540e4c8
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/it/generate-rest-dsl-from-v3/verify.groovy
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+new File(basedir, "document.xml").withReader {
+    def document = new groovy.util.XmlSlurper().parse(it)
+
+    assert document.rest.@path == '/v1'
+    assert document.rest.get.size() == 2
+    assert document.rest.get.find { it.@id == 'listPets' }.@path == '/pets'
+    assert document.rest.get.find { it.@id == 'listPets' }.to.@uri == 'direct:listPets'
+    assert document.rest.get.find { it.@id == 'showPetById' }.@path == '/pets/{petId}'
+    assert document.rest.get.find { it.@id == 'showPetById' }.to.@uri == 'direct:showPetById'
+    assert document.rest.post.find { it.@id == 'createPets' }.@path == '/pets'
+    assert document.rest.post.find { it.@id == 'createPets' }.to.@uri == 'direct:createPets'
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateCatalogMojo.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateCatalogMojo.java
new file mode 100644
index 0000000000..894cfc746e
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateCatalogMojo.java
@@ -0,0 +1,512 @@
+/*
+ * 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.quarkus.k.tooling.maven;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.quarkus.QuarkusRuntimeProvider;
+import org.apache.camel.impl.engine.AbstractCamelContext;
+import org.apache.camel.quarkus.core.FastCamelContext;
+import org.apache.camel.quarkus.k.catalog.model.CamelArtifact;
+import org.apache.camel.quarkus.k.catalog.model.CamelCapability;
+import org.apache.camel.quarkus.k.catalog.model.CamelLoader;
+import org.apache.camel.quarkus.k.catalog.model.CamelScheme;
+import org.apache.camel.quarkus.k.catalog.model.CatalogComponentDefinition;
+import org.apache.camel.quarkus.k.catalog.model.CatalogDataFormatDefinition;
+import org.apache.camel.quarkus.k.catalog.model.CatalogDefinition;
+import org.apache.camel.quarkus.k.catalog.model.CatalogLanguageDefinition;
+import org.apache.camel.quarkus.k.catalog.model.CatalogOtherDefinition;
+import org.apache.camel.quarkus.k.catalog.model.CatalogSupport;
+import org.apache.camel.quarkus.k.catalog.model.k8s.ObjectMeta;
+import org.apache.camel.quarkus.k.catalog.model.k8s.crd.CamelCatalog;
+import org.apache.camel.quarkus.k.catalog.model.k8s.crd.CamelCatalogSpec;
+import org.apache.camel.quarkus.k.catalog.model.k8s.crd.RuntimeSpec;
+import org.apache.camel.quarkus.k.tooling.maven.support.MavenSupport;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+@Mojo(name = "generate-catalog", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = true, requiresProject = false, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
+public class GenerateCatalogMojo extends AbstractMojo {
+    private static final List<String> KNOWN_HTTP_URIS = Arrays.asList(
+            "ahc",
+            "ahc-ws",
+            "atmosphere-websocket",
+            "cxf",
+            "cxfrs",
+            "grpc",
+            "jetty",
+            "knative",
+            "netty-http",
+            "platform-http",
+            "rest",
+            "restlet",
+            "servlet",
+            "spark-rest",
+            "spring-ws",
+            "undertow",
+            "webhook",
+            "websocket");
+
+    private static final List<String> KNOWN_PASSIVE_URIS = Arrays.asList(
+            "bean",
+            "binding",
+            "browse",
+            "class",
+            "controlbus",
+            "dataformat",
+            "dataset",
+            "direct",
+            "direct-vm",
+            "language",
+            "log",
+            "mock",
+            "ref",
+            "seda",
+            "stub",
+            "test",
+            "validator",
+            "vm");
+
+    @Parameter(property = "catalog.dir", defaultValue = "${project.build.directory}")
+    private String outputPath;
+
+    @Parameter(property = "catalog.file", defaultValue = "camel-k-catalog.yaml")
+    private String outputFile;
+
+    @Parameter(property = "components.exclusion.list")
+    private Set<String> componentsExclusionList;
+
+    @Parameter(property = "dataformats.exclusion.list")
+    private Set<String> dataformatsExclusionList;
+
+    @Parameter(property = "languages.exclusion.list")
+    private Set<String> languagesExclusionList;
+
+    @Parameter(property = "others.exclusion.list")
+    private Set<String> othersExclusionList;
+
+    @Parameter(property = "dsls.exclusion.list")
+    private Set<String> dslsExclusionList;
+
+    @Parameter(property = "capabilities.exclusion.list")
+    private Set<String> capabilitiesExclusionList;
+
+    // ********************
+    //
+    // ********************
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        final Path output = Paths.get(this.outputPath, this.outputFile);
+
+        try {
+            if (Files.notExists(output.getParent())) {
+                Files.createDirectories(output.getParent());
+            }
+            if (Files.exists(output)) {
+                Files.delete(output);
+            }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Exception while generating camel catalog", e);
+        }
+
+        final org.apache.camel.catalog.CamelCatalog catalog = new DefaultCamelCatalog();
+        catalog.setRuntimeProvider(new QuarkusRuntimeProvider());
+
+        final String runtimeVersion = MavenSupport.getVersion(getClass(),
+                "/META-INF/maven/org.apache.camel.quarkus.k.camel-k-maven-plugin/pom.properties");
+        final String catalogName = String.format("camel-catalog-%s", runtimeVersion.toLowerCase(Locale.US));
+
+        try {
+            CamelCatalogSpec.Builder catalogSpec = new CamelCatalogSpec.Builder();
+
+            RuntimeSpec.Builder runtimeSpec = new RuntimeSpec.Builder()
+                    .version(runtimeVersion)
+                    .provider("quarkus");
+
+            MavenSupport.getVersion(
+                    AbstractCamelContext.class,
+                    "org.apache.camel", "camel-base",
+                    version -> runtimeSpec.putMetadata("camel.version", version));
+            MavenSupport.getVersion(
+                    FastCamelContext.class,
+                    "io.quarkus", "quarkus-core",
+                    version -> runtimeSpec.putMetadata("quarkus.version", version));
+            MavenSupport.getVersion(
+                    QuarkusRuntimeProvider.class,
+                    "org.apache.camel.quarkus", "camel-quarkus-catalog",
+                    version -> runtimeSpec.putMetadata("camel-quarkus.version", version));
+
+            runtimeSpec.putMetadata("quarkus.native-builder-image",
+                    MavenSupport.getApplicationProperty(getClass(), "quarkus.native-builder-image"));
+
+            runtimeSpec.applicationClass("io.quarkus.bootstrap.runner.QuarkusEntryPoint");
+            runtimeSpec.addDependency("org.apache.camel.quarkus", "camel-quarkus-k-runtime");
+
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("cron")) {
+                runtimeSpec.putCapability(
+                        "cron",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-k-cron"));
+
+                catalogSpec.putArtifact(
+                        new CamelArtifact.Builder()
+                                .groupId("org.apache.camel.quarkus")
+                                .artifactId("camel-k-cron")
+                                .build());
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("health")) {
+                runtimeSpec.putCapability(
+                        "health",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-quarkus-microprofile-health"));
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("platform-http")) {
+                runtimeSpec.putCapability(
+                        "platform-http",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-quarkus-platform-http"));
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("rest")) {
+                runtimeSpec.putCapability(
+                        "rest",
+                        new CamelCapability.Builder()
+                                .addDependency("org.apache.camel.quarkus", "camel-quarkus-rest")
+                                .addDependency("org.apache.camel.quarkus", "camel-quarkus-platform-http")
+                                .build());
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("circuit-breaker")) {
+                runtimeSpec.putCapability(
+                        "circuit-breaker",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-quarkus-microprofile-fault-tolerance"));
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("tracing")) {
+                runtimeSpec.putCapability(
+                        "tracing",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-quarkus-opentracing"));
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("telemetry")) {
+                runtimeSpec.putCapability(
+                        "telemetry",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-quarkus-opentelemetry"));
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("master")) {
+                runtimeSpec.putCapability(
+                        "master",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-k-master"));
+
+                catalogSpec.putArtifact(
+                        new CamelArtifact.Builder()
+                                .groupId("org.apache.camel.quarkus")
+                                .artifactId("camel-k-master")
+                                .build());
+            }
+            if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("resume-kafka")) {
+                runtimeSpec.putCapability(
+                        "resume-kafka",
+                        CamelCapability.forArtifact(
+                                "org.apache.camel.quarkus", "camel-k-resume-kafka"));
+
+                catalogSpec.putArtifact(
+                        new CamelArtifact.Builder()
+                                .groupId("org.apache.camel.quarkus")
+                                .artifactId("camel-k-resume-kafka")
+                                .build());
+            }
+
+            catalogSpec.runtime(runtimeSpec.build());
+
+            process(catalog, catalogSpec);
+
+            ObjectMeta.Builder metadata = new ObjectMeta.Builder()
+                    .name(catalogName)
+                    .putLabels("app", "camel-k")
+                    .putLabels("camel.apache.org/catalog.version", catalog.getCatalogVersion())
+                    .putLabels("camel.apache.org/catalog.loader.version", catalog.getLoadedVersion())
+                    .putLabels("camel.apache.org/runtime.version", runtimeVersion);
+
+            CamelCatalog cr = new CamelCatalog.Builder()
+                    .metadata(metadata.build())
+                    .spec(catalogSpec.build())
+                    .build();
+
+            //
+            // apiVersion: camel.apache.org/v1
+            // kind: CamelCatalog
+            // metadata:
+            //   name: catalog-x.y.z-main
+            //   labels:
+            //     app: "camel-k"
+            //     camel.apache.org/catalog.version: x.y.x
+            //     camel.apache.org/catalog.loader.version: x.y.z
+            //     camel.apache.org/runtime.version: x.y.x
+            //     camel.apache.org/runtime.provider: main
+            // spec:
+            //   version:
+            //   runtimeVersion:
+            // status:
+            //   artifacts:
+            //
+            try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
+
+                YAMLFactory factory = new YAMLFactory()
+                        .configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, true)
+                        .configure(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS, true)
+                        .configure(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID, false)
+                        .configure(YAMLGenerator.Feature.WRITE_DOC_START_MARKER, false);
+
+                // write license header
+                writer.write(
+                        GenerateSupport.getResourceAsString("/catalog-license.txt"));
+
+                getLog().info("Writing catalog file to: " + output);
+
+                // write catalog data
+                ObjectMapper mapper = new ObjectMapper(factory);
+                mapper.registerModule(new Jdk8Module());
+                mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+                mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+                mapper.writeValue(writer, cr);
+            }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Exception while generating catalog", e);
+        }
+    }
+
+    // ********************
+    //
+    // ********************
+
+    public void process(
+            org.apache.camel.catalog.CamelCatalog catalog,
+            CamelCatalogSpec.Builder specBuilder) {
+
+        Map<String, CamelArtifact> artifacts = new TreeMap<>();
+
+        processComponents(catalog, artifacts);
+        processLanguages(catalog, artifacts);
+        processDataFormats(catalog, artifacts);
+        processOthers(catalog, artifacts);
+        processLoaders(specBuilder);
+
+        specBuilder.putAllArtifacts(artifacts);
+    }
+
+    private void processLoaders(CamelCatalogSpec.Builder specBuilder) {
+        if (dslsExclusionList != null) {
+            getLog().info("dsls.exclusion.list: " + dslsExclusionList);
+        }
+
+        if (dslsExclusionList != null && !dslsExclusionList.contains("yaml")) {
+            specBuilder.putLoader(
+                    "yaml",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-yaml-dsl")
+                            .addLanguage("yaml")
+                            .putMetadata("native", "true")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("groovy")) {
+            specBuilder.putLoader(
+                    "groovy",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-groovy-dsl")
+                            .addLanguage("groovy")
+                            .putMetadata("native", "true")
+                            .putMetadata("sources-required-at-build-time", "true")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("kts")) {
+            specBuilder.putLoader(
+                    "kts",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-kotlin-dsl")
+                            .addLanguage("kts")
+                            .putMetadata("native", "true")
+                            .putMetadata("sources-required-at-build-time", "true")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("js")) {
+            specBuilder.putLoader(
+                    "js",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-js-dsl")
+                            .addLanguage("js")
+                            // Guest languages are not yet supported on Mandrel in native mode.
+                            .putMetadata("native", "false")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("xml")) {
+            specBuilder.putLoader(
+                    "xml",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-xml-io-dsl")
+                            .addLanguage("xml")
+                            .putMetadata("native", "true")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("java")) {
+            specBuilder.putLoader(
+                    "java",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-java-joor-dsl")
+                            .addLanguages("java")
+                            .putMetadata("native", "true")
+                            .putMetadata("sources-required-at-build-time", "true")
+                            .build());
+        }
+        if (dslsExclusionList != null && !dslsExclusionList.contains("jsh")) {
+            specBuilder.putLoader(
+                    "jsh",
+                    CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-jsh-dsl")
+                            .addLanguages("jsh")
+                            // Native mode is not yet supported due to https://github.com/apache/camel-quarkus/issues/4458.
+                            .putMetadata("native", "false")
+                            .putMetadata("sources-required-at-build-time", "true")
+                            .build());
+        }
+    }
+
+    private void processComponents(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) {
+        final Set<String> elements = new TreeSet<>(catalog.findComponentNames());
+
+        if (componentsExclusionList != null) {
+            getLog().info("components.exclusion.list: " + componentsExclusionList);
+            elements.removeAll(componentsExclusionList);
+        }
+
+        for (String name : elements) {
+            String json = catalog.componentJSonSchema(name);
+            CatalogComponentDefinition definition = CatalogSupport.unmarshallComponent(json);
+
+            artifacts.compute(definition.getArtifactId(), (key, artifact) -> {
+                CamelArtifact.Builder builder = artifactBuilder(artifact, definition);
+                builder.addJavaType(definition.getJavaType());
+
+                definition.getSchemes().map(StringUtils::trimToNull).filter(Objects::nonNull).forEach(scheme -> {
+                    builder.addScheme(
+                            new CamelScheme.Builder()
+                                    .id(scheme)
+                                    .http(KNOWN_HTTP_URIS.contains(scheme))
+                                    .passive(KNOWN_PASSIVE_URIS.contains(scheme))
+                                    .build());
+                });
+
+                return builder.build();
+            });
+        }
+    }
+
+    private void processLanguages(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) {
+        final Set<String> elements = new TreeSet<>(catalog.findLanguageNames());
+
+        if (languagesExclusionList != null) {
+            getLog().info("languages.exclusion.list: " + languagesExclusionList);
+            elements.removeAll(languagesExclusionList);
+        }
+
+        for (String name : elements) {
+            String json = catalog.languageJSonSchema(name);
+            CatalogLanguageDefinition definition = CatalogSupport.unmarshallLanguage(json);
+
+            artifacts.compute(definition.getArtifactId(), (key, artifact) -> {
+                CamelArtifact.Builder builder = artifactBuilder(artifact, definition);
+                builder.addLanguage(definition.getName());
+                builder.addJavaType(definition.getJavaType());
+
+                return builder.build();
+            });
+        }
+    }
+
+    private void processDataFormats(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) {
+        final Set<String> elements = new TreeSet<>(catalog.findDataFormatNames());
+
+        if (dataformatsExclusionList != null) {
+            getLog().info("dataformats.exclusion.list: " + dataformatsExclusionList);
+            elements.removeAll(dataformatsExclusionList);
+        }
+
+        for (String name : elements) {
+            String json = catalog.dataFormatJSonSchema(name);
+            CatalogDataFormatDefinition definition = CatalogSupport.unmarshallDataFormat(json);
+
+            artifacts.compute(definition.getArtifactId(), (key, artifact) -> {
+                CamelArtifact.Builder builder = artifactBuilder(artifact, definition);
+                builder.addDataformat(definition.getName());
+                builder.addJavaType(definition.getJavaType());
+
+                return builder.build();
+            });
+        }
+    }
+
+    private void processOthers(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) {
+        final Set<String> elements = new TreeSet<>(catalog.findOtherNames());
+
+        if (othersExclusionList != null) {
+            getLog().info("others.exclusion.list: " + othersExclusionList);
+            elements.removeAll(othersExclusionList);
+        }
+
+        for (String name : elements) {
+            String json = catalog.otherJSonSchema(name);
+            CatalogOtherDefinition definition = CatalogSupport.unmarshallOther(json);
+
+            artifacts.compute(definition.getArtifactId(), (key, artifact) -> artifactBuilder(artifact, definition).build());
+        }
+    }
+
+    private CamelArtifact.Builder artifactBuilder(CamelArtifact artifact, CatalogDefinition definition) {
+        CamelArtifact.Builder builder = new CamelArtifact.Builder();
+
+        if (artifact != null) {
+            builder.from(artifact);
+        } else {
+            Objects.requireNonNull(definition.getGroupId());
+            Objects.requireNonNull(definition.getArtifactId());
+
+            builder.groupId(definition.getGroupId());
+            builder.artifactId(definition.getArtifactId());
+        }
+
+        return builder;
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateDependencyListMojo.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateDependencyListMojo.java
new file mode 100644
index 0000000000..306e006255
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateDependencyListMojo.java
@@ -0,0 +1,132 @@
+/*
+ * 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.quarkus.k.tooling.maven;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+import static org.apache.camel.quarkus.k.tooling.maven.support.MavenSupport.sha1Hex;
+
+@Mojo(name = "generate-dependency-list", defaultPhase = LifecyclePhase.PREPARE_PACKAGE, threadSafe = true, requiresProject = false, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
+public class GenerateDependencyListMojo extends AbstractMojo {
+    private static final String[] CHECKSUM_TYPES = { "md5", "sha1" };
+
+    @Parameter(readonly = true, defaultValue = "${project}")
+    private MavenProject project;
+
+    @Parameter(property = "dependencies.file", defaultValue = "${project.build.directory}/dependencies.yaml")
+    private String outputFile;
+
+    @Parameter(defaultValue = "true")
+    private boolean includeLocation;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        final Path output = Paths.get(this.outputFile);
+
+        try {
+            if (Files.notExists(output.getParent())) {
+                Files.createDirectories(output.getParent());
+            }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Exception while generating dependencies list", e);
+        }
+
+        try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
+            List<Map<String, String>> deps = project.getArtifacts().stream()
+                    .filter(this::isCompileOrRuntime)
+                    .map(this::artifactToMap)
+                    .collect(Collectors.toList());
+
+            DumperOptions options = new DumperOptions();
+            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+
+            Yaml yaml = new Yaml(options);
+            yaml.dump(Collections.singletonMap("dependencies", deps), writer);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Exception while generating dependencies list", e);
+        }
+    }
+
+    private boolean isCompileOrRuntime(Artifact artifact) {
+        return Objects.equals(artifact.getScope(), DefaultArtifact.SCOPE_COMPILE)
+                || Objects.equals(artifact.getScope(), DefaultArtifact.SCOPE_RUNTIME);
+    }
+
+    private Map<String, String> artifactToMap(Artifact artifact) {
+        Map<String, String> dep = new LinkedHashMap<>();
+        dep.put("id", artifact.getId());
+
+        if (artifact.getFile() == null) {
+            return dep;
+        }
+
+        if (includeLocation) {
+            dep.put("location", artifact.getFile().getAbsolutePath());
+        }
+
+        try {
+            String location = artifact.getFile().getAbsolutePath();
+            String checksum = null;
+
+            for (String checksumType : CHECKSUM_TYPES) {
+                Path checksumFile = Paths.get(location + "." + checksumType);
+                if (Files.exists(checksumFile)) {
+                    checksum = checksumType + ":" + Files.readString(checksumFile, StandardCharsets.UTF_8);
+                    break;
+                }
+            }
+
+            if (checksum == null) {
+                try (InputStream is = Files.newInputStream(artifact.getFile().toPath())) {
+                    checksum = "sha1:" + sha1Hex(is);
+                }
+            }
+
+            dep.put("checksum", checksum);
+        } catch (IOException | NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+
+        return dep;
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateRestXML.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateRestXML.java
new file mode 100644
index 0000000000..c451167248
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateRestXML.java
@@ -0,0 +1,102 @@
+/*
+ * 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.quarkus.k.tooling.maven;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.models.openapi.OpenApiDocument;
+import io.apicurio.datamodels.models.util.JsonUtil;
+import org.apache.camel.CamelContext;
+import org.apache.camel.generator.openapi.RestDslXmlGenerator;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+@Mojo(name = "generate-rest-xml", inheritByDefault = false, defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresProject = false, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
+class GenerateRestXML extends AbstractMojo {
+    @Parameter(property = "openapi.spec")
+    private String inputFile;
+    @Parameter(property = "dsl.out")
+    private String outputFile;
+
+    @Override
+    public void execute() throws MojoExecutionException {
+        if (inputFile == null) {
+            throw new MojoExecutionException("Missing input file: " + inputFile);
+        }
+
+        Path input = Paths.get(this.inputFile);
+        if (!Files.exists(input)) {
+            throw new MojoExecutionException("Unable to read the input file: " + inputFile);
+        }
+
+        try {
+            JsonFactory factory = null;
+            if (inputFile.endsWith(".yaml") || inputFile.endsWith(".yml")) {
+                factory = new YAMLFactory();
+            }
+
+            ObjectMapper mapper = new ObjectMapper(factory);
+            mapper.findAndRegisterModules();
+
+            FileInputStream fis = new FileInputStream(inputFile);
+
+            JsonNode node = mapper.readTree(fis);
+            OpenApiDocument document = (OpenApiDocument) Library.readDocument(JsonUtil.toObject(node));
+
+            final Writer writer;
+
+            if (outputFile != null) {
+                Path output = Paths.get(this.outputFile);
+
+                if (output.getParent() != null && Files.notExists(output.getParent())) {
+                    Files.createDirectories(output.getParent());
+                }
+                if (Files.exists(output)) {
+                    Files.delete(output);
+                }
+
+                writer = Files.newBufferedWriter(output);
+            } else {
+                writer = new PrintWriter(System.out);
+            }
+
+            final CamelContext context = new DefaultCamelContext();
+            final String dsl = RestDslXmlGenerator.toXml(document).generate(context);
+
+            try (writer) {
+                writer.write(dsl);
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Exception while generating rest xml", e);
+        }
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateSupport.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateSupport.java
new file mode 100644
index 0000000000..ff36c331a6
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/GenerateSupport.java
@@ -0,0 +1,38 @@
+/*
+ * 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.quarkus.k.tooling.maven;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.io.IOUtils;
+
+public final class GenerateSupport {
+    private GenerateSupport() {
+    }
+
+    public static String getResourceAsString(String resource) throws IOException {
+        try (InputStream is = GenerateSupport.class.getResourceAsStream(resource)) {
+            if (is == null) {
+                throw new IllegalStateException("Unable to find catalog-license.txt");
+            }
+
+            return IOUtils.toString(is, StandardCharsets.UTF_8);
+        }
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/support/MavenSupport.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/support/MavenSupport.java
new file mode 100644
index 0000000000..4502fe94a5
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/quarkus/k/tooling/maven/support/MavenSupport.java
@@ -0,0 +1,120 @@
+/*
+ * 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.quarkus.k.tooling.maven.support;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Properties;
+import java.util.function.Consumer;
+
+public final class MavenSupport {
+    private MavenSupport() {
+    }
+
+    public static String getApplicationProperty(Class<?> clazz, String property) {
+        try (InputStream is = clazz.getResourceAsStream("/app.properties")) {
+            Properties p = new Properties();
+            p.load(is);
+            return p.getProperty(property);
+        } catch (Exception ignored) {
+        }
+        return "";
+    }
+
+    public static String getVersion(Class<?> clazz, String path) {
+        String version = null;
+
+        // try to load from maven properties first
+        try (InputStream is = clazz.getResourceAsStream(path)) {
+            if (is != null) {
+                Properties p = new Properties();
+                p.load(is);
+                version = p.getProperty("version", "");
+            }
+        } catch (Exception ignored) {
+        }
+
+        // fallback to using Java API
+        if (version == null) {
+            Package aPackage = clazz.getPackage();
+            if (aPackage != null) {
+                version = getVersion(aPackage);
+            }
+        }
+
+        if (version == null) {
+            // we could not compute the version so use a blank
+            throw new IllegalStateException("Unable to determine runtime version");
+        }
+
+        return version;
+    }
+
+    public static String getVersion(Package pkg) {
+        String version = pkg.getImplementationVersion();
+        if (version == null) {
+            version = pkg.getSpecificationVersion();
+        }
+
+        return version;
+    }
+
+    public static void getVersion(Class<?> clazz, String path, Consumer<String> consumer) {
+        consumer.accept(
+                MavenSupport.getVersion(clazz, path));
+    }
+
+    public static void getVersion(Class<?> clazz, String groupId, String artifactId, Consumer<String> consumer) {
+        getVersion(
+                clazz,
+                String.format("/META-INF/maven/%s/%s/pom.properties", groupId, artifactId),
+                consumer);
+    }
+
+    public static String getVersion(Class<?> clazz, String groupId, String artifactId) {
+        return MavenSupport.getVersion(
+                clazz,
+                String.format("/META-INF/maven/%s/%s/pom.properties", groupId, artifactId));
+    }
+
+    public static String bytesToHex(byte[] hash) {
+        StringBuilder hexString = new StringBuilder();
+        for (byte b : hash) {
+            String hex = Integer.toHexString(0xff & b);
+            if (hex.length() == 1) {
+                hexString.append('0');
+            }
+
+            hexString.append(hex);
+        }
+
+        return hexString.toString();
+    }
+
+    public static String sha1Hex(InputStream is) throws NoSuchAlgorithmException, IOException {
+        MessageDigest digest = MessageDigest.getInstance("SHA-1");
+
+        byte[] buffer = new byte[1024];
+        for (int read = is.read(buffer, 0, 1024); read > -1; read = is.read(buffer, 0, 1024)) {
+            digest.update(buffer, 0, read);
+        }
+
+        return bytesToHex(digest.digest());
+    }
+}
diff --git a/tooling/camel-k-maven-plugin/src/main/resources/app.properties b/tooling/camel-k-maven-plugin/src/main/resources/app.properties
new file mode 100644
index 0000000000..9c5f2cb26f
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/resources/app.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+quarkus.native-builder-image=${quarkus-native-builder-image}
diff --git a/tooling/camel-k-maven-plugin/src/main/resources/catalog-license.txt b/tooling/camel-k-maven-plugin/src/main/resources/catalog-license.txt
new file mode 100644
index 0000000000..658e8dc7ec
--- /dev/null
+++ b/tooling/camel-k-maven-plugin/src/main/resources/catalog-license.txt
@@ -0,0 +1,17 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
diff --git a/tooling/pom.xml b/tooling/pom.xml
index 748afb2770..a91c08a80c 100644
--- a/tooling/pom.xml
+++ b/tooling/pom.xml
@@ -34,6 +34,8 @@
 
     <modules>
         <module>maven-plugin</module>
+        <module>camel-k-catalog-model</module>
+        <module>camel-k-maven-plugin</module>
         <module>perf-regression</module>
         <module>test-list</module>
     </modules>
diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml
index 4f255251f6..b7d99a8ca9 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -203,6 +203,7 @@ group-12:
   - vertx-websocket
 group-13:
   - box
+  - camel-k-runtime
   - fhir
   - github
   - google