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

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

commit 6bc98b8a123b298b7dcc31c71ebceee7aec56d65
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Apr 10 12:09:58 2025 +0200

    CAMEL-21944: camel-jbang - Classpath scan custom JARs for beans and 
processors with dependency injection annotations
---
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../org/apache/camel/catalog/others.properties     |   1 +
 .../org/apache/camel/catalog/others/jandex.json    |  15 ++
 .../bindy/util/AnnotationModuleLoaderTest.java     |   2 +-
 components/camel-jandex/pom.xml                    |  70 ++++++++++
 .../org/apache/camel/jandex-class-resolver         |   2 +
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/jandex.json            |  15 ++
 components/camel-jandex/src/main/docs/jandex.adoc  |  15 ++
 .../jandex/JandexPackageScanClassResolver.java     | 154 +++++++++++++++++++++
 .../camel/component/jcr/JcrConverterTest.java      |   2 +-
 .../component/salesforce/api/utils/JsonUtils.java  |   2 +-
 .../org/apache/camel/spring/SpringTestSupport.java |   6 +-
 .../DefaultPackageResolverConfigureTest.java       |   2 +-
 .../scan/DefaultPackageScanClassResolverTest.java  |   2 +-
 .../camel/spring/scan/PackageScanFiltersTest.java  |  10 +-
 .../camel/spring/config/PackageResolverTest.xml    |   2 +-
 .../test/ExcludingPackageScanClassResolver.java    |   6 +-
 .../camel/impl/engine/SimpleCamelContext.java      |   3 +
 .../java/org/apache/camel/impl/scan/package.html   |  27 ----
 .../org/apache/camel/impl/DefaultCamelContext.java |   4 +-
 .../transformer/AnnotationTransformerLoader.java   |   8 +-
 .../xml/AbstractCamelContextFactoryBeanTest.java   |   2 +-
 .../org/apache/camel/converter/ConverterTest.java  |   2 +-
 .../java/org/apache/camel/converter/JaxpTest.java  |   2 +-
 .../apache/camel/converter/StringSourceTest.java   |   2 +-
 .../apache/camel/model/ModelSanityCheckerTest.java |   2 +-
 .../scan/AnnotatedWithAnyPackageScanFilter.java    |   7 +-
 .../scan/AnnotatedWithPackageScanFilter.java       |   6 +-
 .../scan/AssignableToPackageScanFilter.java        |   7 +-
 .../support/scan}/BasePackageScanResolver.java     |   2 +-
 .../support}/scan/CompositePackageScanFilter.java  |   2 +-
 .../scan}/DefaultPackageScanClassResolver.java     |   6 +-
 .../scan}/DefaultPackageScanResourceResolver.java  |  12 +-
 .../support}/scan/InvertingPackageScanFilter.java  |   2 +-
 .../camel/support/scan/PackageScanJarResource.java |  67 +++++++++
 .../scan}/WebSpherePackageScanClassResolver.java   |   3 +-
 .../modules/others/examples/json/jandex.json       |   1 +
 docs/components/modules/others/nav.adoc            |   1 +
 docs/components/modules/others/pages/jandex.adoc   |   1 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_12.adoc    |  12 ++
 .../modules/ROOT/pages/camel-jbang.adoc            |   6 +
 .../camel/dsl/jbang/core/commands/Export.java      |   1 +
 .../dsl/jbang/core/commands/ExportBaseCommand.java |   7 +-
 .../apache/camel/dsl/jbang/core/commands/Run.java  |   9 ++
 .../core/commands/kubernetes/KubernetesExport.java |   2 +
 .../core/commands/kubernetes/KubernetesRun.java    |  11 +-
 dsl/camel-kamelet-main/pom.xml                     |   4 +
 .../java/org/apache/camel/main/KameletMain.java    |  18 ++-
 .../download/BasePackageScanDownloadListener.java  | 146 ++++++++++++++++++-
 .../injection/AnnotationDependencyInjection.java   |  11 ++
 .../camel-main-known-dependencies.properties       |   1 +
 parent/pom.xml                                     |   5 +
 54 files changed, 637 insertions(+), 88 deletions(-)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 014102d6e44..7c731552fdc 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1077,6 +1077,11 @@
         <artifactId>camel-jacksonxml</artifactId>
         <version>4.12.0-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-jandex</artifactId>
+        <version>4.12.0-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-jasypt</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml 
b/catalog/camel-allcomponents/pom.xml
index 82d6c18ccf3..e788e909b4f 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -946,6 +946,11 @@
             <artifactId>camel-jacksonxml</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-jandex</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-jasypt</artifactId>
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
index 6b15779ac90..3c81f056b44 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties
@@ -14,6 +14,7 @@ elytron
 endpointdsl
 headersmap
 health
+jandex
 jasypt
 java-joor-dsl
 jfr
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json
new file mode 100644
index 00000000000..bb305950e1b
--- /dev/null
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json
@@ -0,0 +1,15 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "jandex",
+    "title": "Jandex",
+    "description": "Custom class and resource loader using jandex.idx",
+    "deprecated": false,
+    "firstVersion": "4.12.0",
+    "label": "core",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-jandex",
+    "version": "4.12.0-SNAPSHOT"
+  }
+}
diff --git 
a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java
 
b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java
index 14927251d9c..a3c8d7fc9d9 100644
--- 
a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java
+++ 
b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java
@@ -21,7 +21,7 @@ import java.util.Set;
 import 
org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Client;
 import 
org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Order;
 import 
org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Security;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/components/camel-jandex/pom.xml b/components/camel-jandex/pom.xml
new file mode 100644
index 00000000000..9ff10c47080
--- /dev/null
+++ b/components/camel-jandex/pom.xml
@@ -0,0 +1,70 @@
+<?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/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>4.12.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-jandex</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: Jandex</name>
+    <description>Custom class and resource loader using 
jandex.idx</description>
+
+    <properties>
+        <firstVersion>4.12.0</firstVersion>
+        <label>core</label>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.smallrye</groupId>
+            <artifactId>jandex</artifactId>
+            <version>${jandex-version}</version>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-mock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver
 
b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver
new file mode 100644
index 00000000000..140c6c47810
--- /dev/null
+++ 
b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.jandex.JandexPackageScanClassResolver
diff --git 
a/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 
b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 00000000000..63affc04782
--- /dev/null
+++ 
b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+name=jandex
+groupId=org.apache.camel
+artifactId=camel-jandex
+version=4.12.0-SNAPSHOT
+projectName=Camel :: Jandex
+projectDescription=Custom class and resource loader using jandex.idx
diff --git a/components/camel-jandex/src/generated/resources/jandex.json 
b/components/camel-jandex/src/generated/resources/jandex.json
new file mode 100644
index 00000000000..bb305950e1b
--- /dev/null
+++ b/components/camel-jandex/src/generated/resources/jandex.json
@@ -0,0 +1,15 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "jandex",
+    "title": "Jandex",
+    "description": "Custom class and resource loader using jandex.idx",
+    "deprecated": false,
+    "firstVersion": "4.12.0",
+    "label": "core",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-jandex",
+    "version": "4.12.0-SNAPSHOT"
+  }
+}
diff --git a/components/camel-jandex/src/main/docs/jandex.adoc 
b/components/camel-jandex/src/main/docs/jandex.adoc
new file mode 100644
index 00000000000..daead9510b9
--- /dev/null
+++ b/components/camel-jandex/src/main/docs/jandex.adoc
@@ -0,0 +1,15 @@
+= Jandex Component
+:doctitle: Jandex
+:shortname: jandex
+:artifactid: camel-jandex
+:description: Custom class and resource loader using jandex.idx
+:since: 4.12
+:supportlevel: Preview
+:tabs-sync-option:
+
+*Since Camel {since}*
+
+The Jandex component is class and resource loader that uses the 
META-INF/jandex.idx index file
+for fast classpath scanning.
+
+This allows much quicker classpath scanning of JARs that has been indexed.
\ No newline at end of file
diff --git 
a/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java
 
b/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java
new file mode 100644
index 00000000000..00426457c64
--- /dev/null
+++ 
b/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java
@@ -0,0 +1,154 @@
+/*
+ * 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.jandex;
+
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.camel.spi.PackageScanFilter;
+import org.apache.camel.spi.PackageScanResourceResolver;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.annotations.JdkService;
+import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter;
+import org.apache.camel.support.scan.AnnotatedWithPackageScanFilter;
+import org.apache.camel.support.scan.AssignableToPackageScanFilter;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
+import org.jboss.jandex.AnnotationTarget;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.Index;
+import org.jboss.jandex.IndexReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@JdkService("jandex-class-resolver")
+public class JandexPackageScanClassResolver extends 
DefaultPackageScanClassResolver {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(JandexPackageScanClassResolver.class);
+
+    private static final String INDEX = "classpath:META-INF/jandex.*";
+    private final List<Index> indexes = new ArrayList<>();
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+
+        PackageScanResourceResolver resolver = 
PluginHelper.getPackageScanResourceResolver(getCamelContext());
+        
resolver.addClassLoader(getCamelContext().getApplicationContextClassLoader());
+        resolver.start();
+
+        var list = resolver.findResources(INDEX);
+
+        for (Resource res : list) {
+            if (res.getLocation().endsWith("jandex.idx")) {
+                try (InputStream is = res.getInputStream()) {
+                    if (is != null) {
+                        LOG.debug("Reading jandex.idx from: {}", 
res.getLocation());
+                        Index index = new IndexReader(is).read();
+                        indexes.add(index);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+        indexes.clear();
+    }
+
+    @Override
+    protected void find(PackageScanFilter test, String packageName, 
ClassLoader loader, Set<Class<?>> classes) {
+        if (test instanceof AnnotatedWithPackageScanFilter ann) {
+            findByAnnotation(ann.getAnnotation(), classes);
+        }
+        if (test instanceof AnnotatedWithAnyPackageScanFilter ann) {
+            for (var c : ann.getAnnotations()) {
+                findByAnnotation(c, classes);
+            }
+        }
+        if (test instanceof AssignableToPackageScanFilter ann) {
+            for (var c : ann.getParents()) {
+                findBySubClass(c, classes);
+            }
+        }
+    }
+
+    private void findByAnnotation(Class<? extends Annotation> c, Set<Class<?>> 
classes) {
+        for (Index index : indexes) {
+            for (var ai : index.getAnnotations(c)) {
+                var at = ai.target();
+                if (at.kind() == AnnotationTarget.Kind.CLASS
+                        && at.asClass().nestingType() == 
ClassInfo.NestingType.TOP_LEVEL) {
+                    if (!at.asClass().isAbstract()) {
+                        String currentClass = at.asClass().name().toString();
+                        for (ClassLoader cl : getClassLoaders()) {
+                            try {
+                                Class<?> clazz = cl.loadClass(currentClass);
+                                classes.add(clazz);
+                                break;
+                            } catch (ClassNotFoundException e) {
+                                // ignore
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void findBySubClass(Class<?> c, Set<Class<?>> classes) {
+        for (Index index : indexes) {
+            if (c.isInterface()) {
+                for (var ai : index.getAllKnownImplementations(c)) {
+                    if (!ai.asClass().isAbstract()) {
+                        String currentClass = ai.asClass().name().toString();
+                        for (ClassLoader cl : getClassLoaders()) {
+                            try {
+                                Class<?> clazz = cl.loadClass(currentClass);
+                                classes.add(clazz);
+                                break;
+                            } catch (ClassNotFoundException e) {
+                                // ignore
+                            }
+                        }
+                    }
+                }
+            } else {
+                for (var ai : index.getAllKnownSubclasses(c)) {
+                    if (!ai.isAbstract()) {
+                        String currentClass = ai.asClass().name().toString();
+                        for (ClassLoader cl : getClassLoaders()) {
+                            try {
+                                Class<?> clazz = cl.loadClass(currentClass);
+                                classes.add(clazz);
+                                break;
+                            } catch (ClassNotFoundException e) {
+                                // ignore
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git 
a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
 
b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
index 5a4fde0243b..28ea74fdea8 100644
--- 
a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
+++ 
b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
@@ -23,9 +23,9 @@ import javax.jcr.Value;
 
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spi.Injector;
 import org.apache.camel.support.ObjectHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.jackrabbit.value.BinaryValue;
 import org.apache.jackrabbit.value.BooleanValue;
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java
 
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java
index 3c7a134372b..e28353da48d 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java
@@ -60,7 +60,7 @@ import 
org.apache.camel.component.salesforce.api.dto.PickListValue;
 import org.apache.camel.component.salesforce.api.dto.SObject;
 import org.apache.camel.component.salesforce.api.dto.SObjectDescription;
 import org.apache.camel.component.salesforce.api.dto.SObjectField;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 
 import static java.util.stream.Collectors.joining;
 
diff --git 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java
 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java
index 0f1617d2dc9..af2e4e7f763 100644
--- 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java
+++ 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java
@@ -30,9 +30,9 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.component.seda.SedaComponent;
 import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
-import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
-import org.apache.camel.impl.scan.InvertingPackageScanFilter;
+import org.apache.camel.support.scan.AssignableToPackageScanFilter;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.InvertingPackageScanFilter;
 import org.apache.camel.util.IOHelper;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
diff --git 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java
 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java
index 52e93b35391..5a36dc85511 100644
--- 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java
+++ 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java
@@ -16,9 +16,9 @@
  */
 package org.apache.camel.spring.config;
 
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spring.SpringTestSupport;
 import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.support.AbstractXmlApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
diff --git 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java
 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java
index f80e2655f8b..c5e1e685dd4 100644
--- 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java
+++ 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java
@@ -22,10 +22,10 @@ import java.net.URLClassLoader;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spring.scan.a.ScanTargetOne;
 import org.apache.camel.spring.scan.b.ScanTargetTwo;
 import org.apache.camel.spring.scan.c.ScanTargetThree;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
diff --git 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java
 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java
index b9ef66f1aec..6fb8ba61f5c 100644
--- 
a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java
+++ 
b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java
@@ -20,15 +20,15 @@ import java.lang.annotation.Annotation;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-import org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter;
-import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter;
-import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
-import org.apache.camel.impl.scan.CompositePackageScanFilter;
-import org.apache.camel.impl.scan.InvertingPackageScanFilter;
 import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.spring.scan.a.ScanTargetOne;
 import org.apache.camel.spring.scan.b.ScanTargetTwo;
 import org.apache.camel.spring.scan.c.ScanTargetThree;
+import org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter;
+import org.apache.camel.support.scan.AnnotatedWithPackageScanFilter;
+import org.apache.camel.support.scan.AssignableToPackageScanFilter;
+import org.apache.camel.support.scan.CompositePackageScanFilter;
+import org.apache.camel.support.scan.InvertingPackageScanFilter;
 import org.apache.camel.util.CollectionHelper;
 import org.junit.jupiter.api.Test;
 
diff --git 
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml
 
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml
index 146b1587ff5..95b25d52e2f 100644
--- 
a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml
+++ 
b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml
@@ -24,7 +24,7 @@
        http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
     ">
 
-   <bean id="myPackageResolver" 
class="org.apache.camel.impl.engine.DefaultPackageScanClassResolver" >
+   <bean id="myPackageResolver" 
class="org.apache.camel.support.scan.DefaultPackageScanClassResolver" >
       <property name="AcceptableSchemes" value="test:;test2:"/>
     </bean>
 
diff --git 
a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java
 
b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java
index 4bcfd9f5a93..1151e429214 100644
--- 
a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java
+++ 
b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java
@@ -19,9 +19,9 @@ package org.apache.camel.test;
 import java.util.Collections;
 import java.util.Set;
 
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
-import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
-import org.apache.camel.impl.scan.InvertingPackageScanFilter;
+import org.apache.camel.support.scan.AssignableToPackageScanFilter;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.InvertingPackageScanFilter;
 
 public class ExcludingPackageScanClassResolver extends 
DefaultPackageScanClassResolver {
 
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index 8cdc1ecf083..8710b8d4c50 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -99,6 +99,9 @@ import org.apache.camel.support.DefaultRegistry;
 import org.apache.camel.support.DefaultUuidGenerator;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.support.ResolverHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.DefaultPackageScanResourceResolver;
+import org.apache.camel.support.scan.WebSpherePackageScanClassResolver;
 import org.apache.camel.support.startup.DefaultStartupConditionStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html 
b/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html
deleted file mode 100644
index 4b17e11ac2c..00000000000
--- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-
-    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.
-
--->
-<html>
-<head>
-</head>
-<body>
-
-Package scan classes.
-
-</body>
-</html>
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 87675091e80..064eabac97c 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -39,8 +39,6 @@ import org.apache.camel.api.management.JmxSystemPropertyKeys;
 import org.apache.camel.impl.engine.DefaultExecutorServiceManager;
 import org.apache.camel.impl.engine.RouteService;
 import org.apache.camel.impl.engine.SimpleCamelContext;
-import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
-import org.apache.camel.impl.scan.InvertingPackageScanFilter;
 import org.apache.camel.model.BeanFactoryDefinition;
 import org.apache.camel.model.DataFormatDefinition;
 import org.apache.camel.model.FaultToleranceConfigurationDefinition;
@@ -81,6 +79,8 @@ import org.apache.camel.support.DefaultRegistry;
 import org.apache.camel.support.LocalBeanRegistry;
 import org.apache.camel.support.ResolverHelper;
 import org.apache.camel.support.SimpleUuidGenerator;
+import org.apache.camel.support.scan.AssignableToPackageScanFilter;
+import org.apache.camel.support.scan.InvertingPackageScanFilter;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.OrderedLocationProperties;
 import org.apache.camel.util.StopWatch;
diff --git 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java
 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java
index 7201b1f55a0..b668c370d3d 100644
--- 
a/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java
+++ 
b/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java
@@ -28,10 +28,8 @@ import java.util.Set;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
-import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Message;
 import org.apache.camel.TypeConverterLoaderException;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.PackageScanClassResolver;
@@ -69,11 +67,7 @@ public class AnnotationTransformerLoader extends Transformer 
implements Transfor
         ObjectHelper.notNull(camelContext, "camelContext");
 
         if (resolver == null) {
-            if (camelContext instanceof ExtendedCamelContext) {
-                resolver = 
PluginHelper.getPackageScanClassResolver(camelContext);
-            } else {
-                resolver = new DefaultPackageScanClassResolver();
-            }
+            resolver = PluginHelper.getPackageScanClassResolver(camelContext);
         }
 
         Set<String> packages = new HashSet<>();
diff --git 
a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
 
b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
index c8ac3be4565..9cbe70da6db 100644
--- 
a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
+++ 
b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
@@ -29,7 +29,6 @@ import org.apache.camel.Service;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.ExecutorServiceManager;
@@ -38,6 +37,7 @@ import org.apache.camel.spi.Injector;
 import org.apache.camel.spi.ManagementNameStrategy;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.support.ObjectHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java 
b/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
index 0c890ed5899..9443555c0ff 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java
@@ -34,10 +34,10 @@ import org.apache.camel.TypeConversionException;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.support.DefaultExchange;
 import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.ReflectionInjector;
 import org.junit.jupiter.api.BeforeEach;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java 
b/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java
index 8d93590bb23..99556b25e67 100644
--- a/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java
@@ -28,7 +28,7 @@ import org.w3c.dom.Element;
 
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.ReflectionInjector;
 import org.junit.jupiter.api.BeforeEach;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java
index f10c71a8ce9..14610d01ee6 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java
@@ -23,7 +23,7 @@ import java.io.ObjectOutputStream;
 
 import org.apache.camel.TypeConverter;
 import org.apache.camel.impl.converter.DefaultTypeConverter;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.ReflectionInjector;
 import org.apache.camel.util.xml.StringSource;
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java
index 3cda42131a5..0837960c160 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java
@@ -27,9 +27,9 @@ import jakarta.xml.bind.annotation.XmlElementRef;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.support.PluginHelper;
+import org.apache.camel.support.scan.DefaultPackageScanClassResolver;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java
similarity index 93%
rename from 
core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java
index 8c3b7be4498..0f66b8b519d 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.scan;
+package org.apache.camel.support.scan;
 
 import java.lang.annotation.Annotation;
 import java.util.Set;
@@ -26,6 +26,7 @@ import org.apache.camel.util.ObjectHelper;
  * Package scan filter for testing if a given class is annotated with any of 
the annotations.
  */
 public class AnnotatedWithAnyPackageScanFilter implements PackageScanFilter {
+
     private final Set<Class<? extends Annotation>> annotations;
     private final boolean checkMetaAnnotations;
 
@@ -51,6 +52,10 @@ public class AnnotatedWithAnyPackageScanFilter implements 
PackageScanFilter {
         return false;
     }
 
+    public Set<Class<? extends Annotation>> getAnnotations() {
+        return annotations;
+    }
+
     @Override
     public String toString() {
         return "annotated with any @[" + annotations + "]";
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java
similarity index 93%
rename from 
core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java
index f30b67d466a..b4d51ee5a37 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.scan;
+package org.apache.camel.support.scan;
 
 import java.lang.annotation.Annotation;
 
@@ -43,6 +43,10 @@ public class AnnotatedWithPackageScanFilter implements 
PackageScanFilter {
         return type != null && ObjectHelper.hasAnnotation(type, annotation, 
checkMetaAnnotations);
     }
 
+    public Class<? extends Annotation> getAnnotation() {
+        return annotation;
+    }
+
     @Override
     public String toString() {
         return "annotated with @" + annotation.getSimpleName();
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java
similarity index 95%
rename from 
core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java
index 2c527e892a1..4e0a2609cb4 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.scan;
+package org.apache.camel.support.scan;
 
 import java.lang.reflect.Modifier;
 import java.util.HashSet;
@@ -26,6 +26,7 @@ import org.apache.camel.spi.PackageScanFilter;
  * Package scan filter for testing if a given class is assignable to another 
class.
  */
 public class AssignableToPackageScanFilter implements PackageScanFilter {
+
     private final Set<Class<?>> parents = new HashSet<>();
     private boolean includeAbstract;
 
@@ -40,6 +41,10 @@ public class AssignableToPackageScanFilter implements 
PackageScanFilter {
         this.parents.addAll(parents);
     }
 
+    public Set<Class<?>> getParents() {
+        return parents;
+    }
+
     public void addParentType(Class<?> parentType) {
         parents.add(parentType);
     }
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java
similarity index 99%
rename from 
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java
index b8de017669c..538914ba8a3 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.engine;
+package org.apache.camel.support.scan;
 
 import java.io.IOException;
 import java.net.URI;
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java
similarity index 97%
rename from 
core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java
index 8ba1c4c0bca..0a17184b6be 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.scan;
+package org.apache.camel.support.scan;
 
 import java.util.LinkedHashSet;
 import java.util.Set;
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java
similarity index 98%
rename from 
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java
index 3e1dff0f322..7be2ef5165d 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.engine;
+package org.apache.camel.support.scan;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -35,10 +35,6 @@ import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 
 import org.apache.camel.NonManagedService;
-import org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter;
-import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter;
-import org.apache.camel.impl.scan.AssignableToPackageScanFilter;
-import org.apache.camel.impl.scan.CompositePackageScanFilter;
 import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.support.LRUCacheFactory;
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java
similarity index 97%
rename from 
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java
index 563a6c09b9d..4c177251ae7 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.engine;
+package org.apache.camel.support.scan;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -174,8 +174,7 @@ public class DefaultPackageScanResourceResolver extends 
BasePackageScanResolver
                         LOG.trace("Loading from jar using file: {}", file);
                         stream = new FileInputStream(file);
                     }
-
-                    loadImplementationsInJar(packageName, subPattern, stream, 
urlPath, resources);
+                    loadImplementationsInJar(url, packageName, subPattern, 
stream, urlPath, resources);
                 }
             } catch (IOException e) {
                 // use debug logging to avoid being to noisy in logs
@@ -195,6 +194,7 @@ public class DefaultPackageScanResourceResolver extends 
BasePackageScanResolver
      * @param resources   the list to add loaded resources
      */
     protected void loadImplementationsInJar(
+            URL url,
             String packageName,
             String subPattern,
             InputStream stream,
@@ -207,9 +207,8 @@ public class DefaultPackageScanResourceResolver extends 
BasePackageScanResolver
             boolean match = PATH_MATCHER.match(subPattern, shortName);
             LOG.debug("Found resource: {} matching pattern: {} -> {}", 
shortName, subPattern, match);
             if (match) {
-                final ResourceLoader loader = 
PluginHelper.getResourceLoader(getCamelContext());
-
-                resources.add(loader.resolveResource(name));
+                Resource resource = new PackageScanJarResource("jar", url, 
name);
+                resources.add(resource);
             }
         }
     }
@@ -281,7 +280,6 @@ public class DefaultPackageScanResourceResolver extends 
BasePackageScanResolver
                 LOG.debug("Found resource: {} matching pattern: {} -> {}", 
name, subPattern, match);
                 if (match) {
                     final ResourceLoader loader = 
PluginHelper.getResourceLoader(getCamelContext());
-
                     resources.add(loader.resolveResource("file:" + 
file.getPath()));
                 }
             }
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java
similarity index 97%
rename from 
core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java
index b072f1bf8db..6b5b2460cfe 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.scan;
+package org.apache.camel.support.scan;
 
 import org.apache.camel.spi.PackageScanFilter;
 
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java
new file mode 100644
index 00000000000..3ef8693a4bb
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.support.scan;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import org.apache.camel.support.ResourceSupport;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.StringHelper;
+
+public class PackageScanJarResource extends ResourceSupport {
+
+    private final URL url;
+    private final URLClassLoader uc;
+
+    public PackageScanJarResource(String scheme, URL url, String location) {
+        super(scheme, url.getFile() + FileUtil.stripPath(location));
+        this.url = url;
+        this.uc = new URLClassLoader(new URL[] { url });
+    }
+
+    @Override
+    public URL getURL() throws MalformedURLException {
+        return url;
+    }
+
+    @Override
+    public boolean exists() {
+        return true;
+    }
+
+    @Override
+    public URI getURI() {
+        try {
+            return url.toURI();
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        String loc = StringHelper.after(getLocation(), "!");
+        return uc.getResourceAsStream(loc);
+    }
+
+}
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java
similarity index 98%
rename from 
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java
index 250f593414b..3b26c38a42a 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.impl.engine;
+package org.apache.camel.support.scan;
 
 import java.io.IOException;
 import java.net.URL;
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
 /**
  * WebSphere specific resolver to handle loading annotated resources in JAR 
files.
  */
+@Deprecated
 public class WebSpherePackageScanClassResolver extends 
DefaultPackageScanClassResolver {
     private static final Logger LOG = 
LoggerFactory.getLogger(WebSpherePackageScanClassResolver.class);
 
diff --git a/docs/components/modules/others/examples/json/jandex.json 
b/docs/components/modules/others/examples/json/jandex.json
new file mode 120000
index 00000000000..074f26f1f8a
--- /dev/null
+++ b/docs/components/modules/others/examples/json/jandex.json
@@ -0,0 +1 @@
+../../../../../../components/camel-jandex/src/generated/resources/jandex.json
\ No newline at end of file
diff --git a/docs/components/modules/others/nav.adoc 
b/docs/components/modules/others/nav.adoc
index 9bac32ee593..f1c13d88801 100644
--- a/docs/components/modules/others/nav.adoc
+++ b/docs/components/modules/others/nav.adoc
@@ -20,6 +20,7 @@
 *** xref:yaml-dsl.adoc[YAML DSL]
 ** xref:elytron.adoc[Elytron]
 ** xref:headersmap.adoc[Headersmap]
+** xref:jandex.adoc[Jandex]
 ** xref:jasypt.adoc[Jasypt]
 ** xref:jfr.adoc[JFR]
 ** xref:jta.adoc[JTA]
diff --git a/docs/components/modules/others/pages/jandex.adoc 
b/docs/components/modules/others/pages/jandex.adoc
new file mode 120000
index 00000000000..aa13a8a514e
--- /dev/null
+++ b/docs/components/modules/others/pages/jandex.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-jandex/src/main/docs/jandex.adoc
\ No newline at end of file
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc
index 0db3d8f98cc..402ae9bac05 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc
@@ -6,6 +6,18 @@ from both 4.0 to 4.1 and 4.1 to 4.2.
 
 == Upgrading Camel 4.11 to 4.12
 
+=== camel-core
+
+The package scan classes has moved from `camel-base-engine` to `camel-support` 
JAR and moved to a new package:
+
+- `org.apache.camel.impl.engine.DefaultPackageScanClassResolver` is moved to 
`org.apache.camel.support.scan.DefaultPackageScanClassResolver`
+- `org.apache.camel.impl.engine.DefaultPackageScanResourceResolver` is moved 
to `org.apache.camel.support.scan.DefaultPackageScanResourceResolver`
+- `org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter` is moved to 
`org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter`
+- `org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter` is moved to 
`org.apache.camel.support.scan.AnnotatedWithPackageScanFilter`
+- `org.apache.camel.impl.scan.AssignableToPackageScanFilter` is moved to 
`org.apache.camel.support.scan.AssignableToPackageScanFilter`
+- `org.apache.camel.impl.scan.CompositePackageScanFilter` is moved to 
`org.apache.camel.support.scan.CompositePackageScanFilter`
+- `org.apache.camel.impl.scan.InvertingPackageScanFilter` is moved to 
`org.apache.camel.support.scan.InvertingPackageScanFilter`
+
 === camel-as2
 
 Add options allowing the addition of an `Authorization` header for Basic or 
Bearer authentication to client and
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index b58521539b6..a8403bf4b8c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -3853,6 +3853,12 @@ The follow options related to _exporting_, can be 
configured in `application.pro
 |`camel.jbang.mavenApacheSnapshotEnabled`
 |Whether downloading JARs from ASF Maven Snapshot repository is enabled
 
+|`camel.jbang.download`
+Whether to allow automatic downloading JAR dependencies (over the internet)
+
+|`camel.jbang.packageScanJars`
+Whether to automatic package scan JARs for custom Spring or Quarkus beans 
making them available for Camel JBang
+
 |`camel.jbang.exportDir`
 |Directory where the project will be exported
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
index c7a8578886a..7b70debeff5 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
@@ -149,6 +149,7 @@ public class Export extends ExportBaseCommand {
         cmd.cleanExportDir = this.cleanExportDir;
         cmd.fresh = this.fresh;
         cmd.download = this.download;
+        cmd.packageScanJars = this.packageScanJars;
         cmd.javaVersion = this.javaVersion;
         cmd.camelVersion = this.camelVersion;
         cmd.kameletsVersion = this.kameletsVersion;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index 3d3fcdc5b7d..597dc4470b6 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -221,11 +221,15 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                         description = "Whether to allow automatic downloading 
JAR dependencies (over the internet)")
     protected boolean download = true;
 
+    @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = 
"false",
+                        description = "Whether to automatic package scan JARs 
for custom Spring or Quarkus beans making them available for Camel JBang")
+    protected boolean packageScanJars;
+
     @CommandLine.Option(names = { "--build-property" },
                         description = "Maven/Gradle build properties, ex. 
--build-property=prop1=foo")
     protected List<String> buildProperties = new ArrayList<>();
 
-    @CommandLine.Option(names = { "--property" },
+    @CommandLine.Option(names = { "--prop", "--property" },
                         description = "Camel application properties, ex. 
--property=prop1=foo")
     protected String[] applicationProperties;
 
@@ -334,6 +338,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
         run.excludes = excludes;
         run.openapi = openapi;
         run.download = download;
+        run.packageScanJars = packageScanJars;
         run.runtime = runtime;
         run.camelVersion = camelVersion;
         run.camelSpringBootVersion = camelSpringBootVersion;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index b4a0c2dcbe8..724ac94dd37 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -213,6 +213,10 @@ public class Run extends CamelCommand {
             description = "Whether to allow automatic downloading JAR 
dependencies (over the internet)")
     boolean download = true;
 
+    @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = 
"false",
+                        description = "Whether to automatic package scan JARs 
for custom Spring or Quarkus beans making them available for Camel JBang")
+    boolean packageScanJars;
+
     @Option(names = { "--jvm-debug" }, parameterConsumer = 
DebugConsumer.class, paramLabel = "<true|false|port>",
             description = "To enable JVM remote debugging on port 4004 by 
default. The supported values are true to " +
                           "enable the remote debugging, false to disable the 
remote debugging or a number to use a custom port")
@@ -552,6 +556,7 @@ public class Run extends CamelCommand {
             main.setRepositories(String.join(",", repositories));
         }
         main.setDownload(download);
+        main.setPackageScanJars(packageScanJars);
         main.setFresh(fresh);
         main.setMavenSettings(mavenSettings);
         main.setMavenSettingsSecurity(mavenSettingsSecurity);
@@ -1010,6 +1015,7 @@ public class Run extends CamelCommand {
         eq.addDependencies("camel:cli-connector");
         eq.fresh = this.fresh;
         eq.download = this.download;
+        eq.packageScanJars = this.packageScanJars;
         eq.quiet = true;
         eq.logging = false;
         eq.loggingLevel = "off";
@@ -1086,6 +1092,7 @@ public class Run extends CamelCommand {
         }
         eq.fresh = this.fresh;
         eq.download = this.download;
+        eq.packageScanJars = this.packageScanJars;
         eq.quiet = true;
         eq.logging = false;
         eq.loggingLevel = "off";
@@ -1223,6 +1230,8 @@ public class Run extends CamelCommand {
                     mavenApacheSnapshotEnabled ? "true" : "false"));
             openapi = answer.getProperty("camel.jbang.open-api", openapi);
             download = 
"true".equals(answer.getProperty("camel.jbang.download", download ? "true" : 
"false"));
+            packageScanJars
+                    = 
"true".equals(answer.getProperty("camel.jbang.packageScanJars", packageScanJars 
? "true" : "false"));
             background = 
"true".equals(answer.getProperty("camel.jbang.background", background ? "true" 
: "false"));
             backgroundWait = 
"true".equals(answer.getProperty("camel.jbang.backgroundWait", backgroundWait ? 
"true" : "false"));
             jvmDebugPort = 
parseJvmDebugPort(answer.getProperty("camel.jbang.jvmDebug", 
Integer.toString(jvmDebugPort)));
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
index 37c3031154c..1ff2cba6658 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
@@ -172,6 +172,7 @@ public class KubernetesExport extends Export {
         gradleWrapper = configurer.gradleWrapper;
         fresh = configurer.fresh;
         download = configurer.download;
+        packageScanJars = configurer.packageScanJars;
         quiet = configurer.quiet;
         logging = configurer.logging;
         loggingLevel = configurer.loggingLevel;
@@ -583,6 +584,7 @@ public class KubernetesExport extends Export {
             boolean gradleWrapper,
             boolean fresh,
             boolean download,
+            boolean packageScanJars,
             boolean quiet,
             boolean logging,
             String loggingLevel,
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
index 9df633f1cac..418750fc82f 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
@@ -193,6 +193,14 @@ public class KubernetesRun extends KubernetesBaseCommand {
     @CommandLine.Option(names = { "--exclude" }, description = "Exclude files 
by name or pattern")
     List<String> excludes = new ArrayList<>();
 
+    @CommandLine.Option(names = { "--download" }, defaultValue = "true",
+                        description = "Whether to allow automatic downloading 
JAR dependencies (over the internet)")
+    boolean download = true;
+
+    @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = 
"false",
+                        description = "Whether to automatic package scan JARs 
for custom Spring or Quarkus beans making them available for Camel JBang")
+    boolean packageScanJars;
+
     @CommandLine.Option(names = { "--maven-settings" },
                         description = "Optional location of Maven settings.xml 
file to configure servers, repositories, mirrors and proxies."
                                       + " If set to \"false\", not even the 
default ~/.m2/settings.xml will be used.")
@@ -397,7 +405,8 @@ public class KubernetesRun extends KubernetesBaseCommand {
                 true,
                 false,
                 true,
-                true,
+                download,
+                packageScanJars,
                 (quiet || output != null),
                 true,
                 "info",
diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml
index 638e5cf3c0a..1a626f49ec7 100644
--- a/dsl/camel-kamelet-main/pom.xml
+++ b/dsl/camel-kamelet-main/pom.xml
@@ -122,6 +122,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-yaml-dsl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-jandex</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-catalog</artifactId>
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 148dca9e966..0508fb78b8d 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -119,6 +119,7 @@ public class KameletMain extends MainCommandLineSupport {
     protected final MainRegistry registry = new MainRegistry();
     private String profile = "dev";
     private boolean download = true;
+    private boolean packageScanJars;
     private String repositories;
     private boolean fresh;
     private boolean verbose;
@@ -228,6 +229,17 @@ public class KameletMain extends MainCommandLineSupport {
         this.download = download;
     }
 
+    public boolean isPackageScanJars() {
+        return packageScanJars;
+    }
+
+    /**
+     * Whether to automatic package scan JARs for custom Spring or Quarkus 
beans making them available for Camel JBang
+     */
+    public void setPackageScanJars(boolean packageScanJars) {
+        this.packageScanJars = packageScanJars;
+    }
+
     public String getRepositories() {
         return repositories;
     }
@@ -489,8 +501,8 @@ public class KameletMain extends MainCommandLineSupport {
 
         // load camel component and custom health-checks
         answer.setLoadHealthChecks(true);
-        // annotation based dependency injection for camel/spring/quarkus 
annotations in DSLs and Java beans
 
+        // annotation based dependency injection for camel/spring/quarkus 
annotations in DSLs and Java beans
         boolean lazyBean = 
"true".equals(getInitialProperties().get(getInstanceType() + ".lazyBean"));
         new AnnotationDependencyInjection(answer, lazyBean);
 
@@ -714,6 +726,7 @@ public class KameletMain extends MainCommandLineSupport {
     private MavenDependencyDownloader 
createMavenDependencyDownloader(ClassLoader dynamicCL, DefaultCamelContext 
answer) {
         KnownReposResolver knownRepos = new KnownReposResolver();
         knownRepos.loadKnownDependencies();
+
         MavenDependencyDownloader downloader = new MavenDependencyDownloader();
         downloader.setDownload(download);
         downloader.setKnownReposResolver(knownRepos);
@@ -726,13 +739,12 @@ public class KameletMain extends MainCommandLineSupport {
         downloader.setMavenSettingsSecurity(mavenSettingsSecurity);
         downloader.setMavenCentralEnabled(mavenCentralEnabled);
         downloader.setMavenApacheSnapshotEnabled(mavenApacheSnapshotEnabled);
-
         if (downloadListener != null) {
             downloader.addDownloadListener(downloadListener);
         }
         downloader.addDownloadListener(new AutoConfigureDownloadListener());
         downloader.addArtifactDownloadListener(new 
TypeConverterLoaderDownloadListener());
-        downloader.addArtifactDownloadListener(new 
BasePackageScanDownloadListener());
+        downloader.addArtifactDownloadListener(new 
BasePackageScanDownloadListener(packageScanJars));
 
         return downloader;
     }
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java
 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java
index 4a8281d3110..daa31b4aee2 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java
@@ -17,29 +17,49 @@
 package org.apache.camel.main.download;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.function.Supplier;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Singleton;
+
+import javax.inject.Named;
 
 import org.apache.camel.CamelConfiguration;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Configuration;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.PluginHelper;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.StringHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
 
 public class BasePackageScanDownloadListener implements 
ArtifactDownloadListener, CamelContextAware {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(BasePackageScanDownloadListener.class);
 
     private CamelContext camelContext;
-
     private final Set<String> scanned = new HashSet<>();
+    private final boolean packageScanJars;
+
+    public BasePackageScanDownloadListener(boolean packageScanJars) {
+        this.packageScanJars = packageScanJars;
+    }
 
     @Override
     public CamelContext getCamelContext() {
@@ -55,15 +75,44 @@ public class BasePackageScanDownloadListener implements 
ArtifactDownloadListener
     public void onDownloadedFile(File file) {
         String basePackage = 
camelContext.getCamelContextExtension().getBasePackageScan();
         if (basePackage != null) {
-            try {
-                basePackageScanConfiguration(basePackage, file);
-            } catch (Exception e) {
-                // ignore
+            packageScan(basePackage);
+        }
+        if (packageScanJars) {
+            String ext = FileUtil.onlyExt(file.getName(), true);
+            if ("jar".equals(ext)) {
+                try {
+                    Set<String> packages = new HashSet<>();
+                    JarInputStream is = new JarInputStream(new 
FileInputStream(file));
+                    JarEntry entry;
+                    while ((entry = is.getNextJarEntry()) != null) {
+                        final String name = entry.getName().trim();
+                        if (!entry.isDirectory() && name.endsWith(".class")) {
+                            packages.add(FileUtil.onlyPath(name));
+                        }
+                    }
+                    if (!packages.isEmpty()) {
+                        String[] arr = packages.toArray(new String[0]);
+                        packageScan(arr);
+                    }
+                    IOHelper.close(is);
+                } catch (Exception e) {
+                    // ignore
+                }
             }
         }
     }
 
-    protected void basePackageScanConfiguration(String basePackage, File file) 
throws Exception {
+    public void packageScan(String... basePackage) {
+        try {
+            basePackageScanConfiguration(basePackage);
+            basePackageScanSpring(basePackage);
+            basePackageScanQuarkus(basePackage);
+        } catch (Exception e) {
+            // ignore
+        }
+    }
+
+    protected void basePackageScanConfiguration(String... basePackage) throws 
Exception {
         Collection<CamelConfiguration> configs = new ArrayList<>();
         // we only want to scan via isolated classloader
         PackageScanClassResolver pscr = 
PluginHelper.getPackageScanClassResolver(camelContext);
@@ -102,4 +151,89 @@ public class BasePackageScanDownloadListener implements 
ArtifactDownloadListener
         }
     }
 
+    protected void basePackageScanQuarkus(String... basePackage) throws 
Exception {
+        // we only want to scan via isolated classloader
+        PackageScanClassResolver pscr = 
PluginHelper.getPackageScanClassResolver(camelContext);
+        Set<Class<?>> found = 
pscr.findAnnotated(Set.of(ApplicationScoped.class, Singleton.class), 
basePackage);
+        for (Class<?> clazz : found) {
+            // avoid duplicate if we scan other JARs that can same class from 
previous downloads
+            String fqn = clazz.getName();
+            if (scanned.contains(fqn)) {
+                continue;
+            } else {
+                scanned.add(fqn);
+            }
+
+            LOG.debug("Discovered Quarkus @ApplicationScoped/@Singleton class: 
{}", clazz);
+
+            // @Named can dictate the name of the bean
+            String name = null;
+            Named named = clazz.getAnnotation(Named.class);
+            if (named != null) {
+                name = named.value();
+            }
+            if (name == null || name.isBlank()) {
+                name = clazz.getSimpleName();
+                // lower case first if using class name
+                name = StringHelper.decapitalize(name);
+            }
+            // must be lazy as we do not know if the bean is in use or not
+            Supplier<Object> supplier = () -> 
camelContext.getInjector().newInstance(clazz, true);
+            bindBean(camelContext, clazz, name, supplier, "Quarkus 
@ApplicationScoped/@Singleton");
+        }
+    }
+
+    protected void basePackageScanSpring(String... basePackage) throws 
Exception {
+        // we only want to scan via isolated classloader
+        PackageScanClassResolver pscr = 
PluginHelper.getPackageScanClassResolver(camelContext);
+        Set<Class<?>> found = pscr.findAnnotated(Set.of(Component.class, 
Service.class), basePackage);
+        for (Class<?> clazz : found) {
+            // avoid duplicate if we scan other JARs that can same class from 
previous downloads
+            String fqn = clazz.getName();
+            if (scanned.contains(fqn)) {
+                continue;
+            } else {
+                scanned.add(fqn);
+            }
+
+            LOG.debug("Discovered Spring @Component/@Service class: {}", 
clazz);
+
+            String name = null;
+            var ann = clazz.getAnnotation(Component.class);
+            if (ann != null) {
+                name = ann.value();
+            } else {
+                var ann2 = clazz.getAnnotation(Service.class);
+                if (ann2 != null) {
+                    name = ann2.value();
+                }
+            }
+            if (name == null || name.isBlank()) {
+                name = clazz.getSimpleName();
+                // lower case first if using class name
+                name = StringHelper.decapitalize(name);
+            }
+            // must be lazy as we do not know if the bean is in use or not
+            Supplier<Object> supplier = () -> 
camelContext.getInjector().newInstance(clazz, true);
+            bindBean(camelContext, clazz, name, supplier, "Spring 
@Component/@Service");
+        }
+    }
+
+    private static void bindBean(CamelContext context, Class<?> type, String 
name, Supplier<Object> supplier, String kind) {
+        // to support hot reloading of beans then we need to enable unbind 
mode in bean post processor
+        Registry registry = context.getRegistry();
+        CamelBeanPostProcessor bpp = 
PluginHelper.getBeanPostProcessor(context);
+        bpp.setUnbindEnabled(true);
+        try {
+            // re-bind the bean to the registry
+            registry.unbind(name);
+            LOG.debug("Lazy binding {} bean: {} of type: {}", kind, name, 
type);
+            registry.bind(name, type, supplier);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeException(e);
+        } finally {
+            bpp.setUnbindEnabled(false);
+        }
+    }
+
 }
diff --git 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
index 07000bfa8aa..bb2a8892f99 100644
--- 
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
+++ 
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java
@@ -48,6 +48,7 @@ import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.ReflectionHelper;
+import org.apache.camel.util.StringHelper;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -212,6 +213,11 @@ public final class AnnotationDependencyInjection {
                 } else if (service != null && 
ObjectHelper.isNotEmpty(service.value())) {
                     name = service.value();
                 }
+                if (name == null || name.isBlank()) {
+                    name = clazz.getSimpleName();
+                    // lower case first if using class name
+                    name = StringHelper.decapitalize(name);
+                }
                 bindBean(camelContext, name, instance, true);
             }
         }
@@ -292,6 +298,11 @@ public final class AnnotationDependencyInjection {
                 if (named != null) {
                     name = named.value();
                 }
+                if (name == null || name.isBlank()) {
+                    name = clazz.getSimpleName();
+                    // lower case first if using class name
+                    name = StringHelper.decapitalize(name);
+                }
                 bindBean(camelContext, name, instance, true);
             }
         }
diff --git 
a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
 
b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
index 1e2747ca73b..0d180bcdfac 100644
--- 
a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
+++ 
b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties
@@ -34,6 +34,7 @@ META-INF/services/org/apache/camel/modelyaml-dumper = 
camel:yaml-io
 META-INF/services/org/apache/camel/micrometer-prometheus = 
camel:micrometer-prometheus
 META-INF/services/org/apache/camel/cron/cron-service = camel:quartz
 META-INF/services/org/apache/camel/platform-http/jolokia = 
camel:camel-platform-http-jolokia
+META-INF/services/org/apache/camel/jandex-class-resolver = camel:jandex
 org.apache.camel.component.activemq.ActiveMQComponent\:embedded\=true = 
org.apache.activemq:activemq-broker:5.19.0
 org.apache.camel.component.activemq6.ActiveMQComponent\:embedded\=true = 
org.apache.activemq:activemq-broker:6.1.6
 spring.datasource.url = 
org.springframework.boot:spring-boot-starter-jdbc:${spring-boot-version}
diff --git a/parent/pom.xml b/parent/pom.xml
index 80688746566..ce08ce7c659 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1584,6 +1584,11 @@
                 <artifactId>camel-jacksonxml</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-jandex</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-jasypt</artifactId>

Reply via email to