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

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

commit 31407635006759958d927c01890a4efa2cad08c8
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jan 31 12:57:58 2022 +0100

    CAMEL-17567: camel-main - Add basePackageScan to auto discover route 
builders, configuration classes, and type converters.
---
 .../main/camel-main-configuration-metadata.json    |   3 +-
 .../org/apache/camel/ExtendedCamelContext.java     |  14 +++
 .../camel/spi/AnnotationScanTypeConverters.java    |   2 +-
 .../camel/impl/engine/AbstractCamelContext.java    |  16 ++-
 .../impl/engine/DefaultCamelBeanPostProcessor.java |   6 ++
 .../apache/camel/impl/engine/DefaultInjector.java  |  11 ++-
 .../converter/AnnotationTypeConverterLoader.java   |  21 ++--
 .../camel/impl/converter/DefaultTypeConverter.java |  12 ++-
 .../camel/impl/ExtendedCamelContextConfigurer.java |   6 ++
 .../camel/impl/lw/LightweightCamelContext.java     |  10 ++
 .../impl/lw/LightweightRuntimeCamelContext.java    |  12 +++
 .../MainConfigurationPropertiesConfigurer.java     |  20 ++--
 .../camel-main-configuration-metadata.json         |   3 +-
 core/camel-main/src/main/docs/main.adoc            |  76 ++++++++++++++-
 .../org/apache/camel/main/BaseMainSupport.java     |  53 +++++++++-
 .../org/apache/camel/main/CamelConfiguration.java} |  21 ++--
 .../src/main/java/org/apache/camel/main/Main.java  |  26 ++++-
 .../apache/camel/main/MainCommandLineSupport.java  |   3 +-
 .../camel/main/MainConfigurationProperties.java    | 107 +++++++++++++--------
 .../java/org/apache/camel/main/MainSupport.java    |   7 +-
 .../org/apache/camel/main/RoutesConfigurer.java    |  14 +--
 .../org/apache/camel/main/ContextEventsTest.java   |   2 +-
 .../org/apache/camel/main/MainCustomizerTest.java  |   8 +-
 .../camel/main/MainIoCNewRouteBuilderTest.java     |   2 +-
 .../java/org/apache/camel/main/MainIoCTest.java    |   4 +-
 .../main/MainRoutesCollectorPackageScanTest.java   |  10 +-
 .../org/apache/camel/main/scan/MyConverter.java}   |  28 +++---
 .../camel/main/scan/MyScanConfiguration.java}      |  27 +++---
 .../ROOT/pages/camel-3x-upgrade-guide-3_16.adoc    |  12 +++
 .../modules/ROOT/pages/camel-3x-upgrade-guide.adoc |   1 +
 30 files changed, 407 insertions(+), 130 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index f68a484..0eaab4a 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -19,6 +19,8 @@
     { "name": "camel.main.autoStartup", "description": "Sets whether the 
object should automatically start when Camel starts. Important: Currently only 
routes can be disabled, as CamelContext's are always started. Note: When 
setting auto startup false on CamelContext then that takes precedence and no 
routes are started. You would need to start CamelContext explicit using the 
org.apache.camel.CamelContext.start() method, to start the context, and then 
you would need to start the routes ma [...]
     { "name": "camel.main.autowiredEnabled", "description": "Whether 
autowiring is enabled. This is used for automatic autowiring options (the 
option must be marked as autowired) by looking up in the registry to find if 
there is a single instance of matching type, which then gets configured on the 
component. This can be used for automatic configuring JDBC data sources, JMS 
connection factories, AWS Clients, etc. Default is true.", "sourceType": 
"org.apache.camel.main.DefaultConfiguration [...]
     { "name": "camel.main.backlogTracing", "description": "Sets whether 
backlog tracing is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.main.basePackageScan", "description": "Package name to 
use as base (offset) for classpath scanning of RouteBuilder , and 
org.apache.camel.TypeConverter classes. If you are using Spring Boot then it is 
instead recommended to use Spring Boots component scanning and annotate your 
route builder classes with Component. In other words only use this for Camel 
Main in standalone mode.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", "jav 
[...]
+    { "name": "camel.main.basePackageScanEnabled", "description": "Whether 
base package scan is enabled.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": true },
     { "name": "camel.main.beanIntrospectionExtendedStatistics", "description": 
"Sets whether bean introspection uses extended statistics. The default is 
false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", 
"type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.beanIntrospectionLoggingLevel", "description": "Sets 
the logging level used by bean introspection, logging activity of its usage. 
The default is TRACE.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "object", 
"javaType": "org.apache.camel.LoggingLevel", "enum": [ "ERROR", "WARN", "INFO", 
"DEBUG", "TRACE", "OFF" ] },
     { "name": "camel.main.beanPostProcessorEnabled", "description": "Can be 
used to turn off bean post processing. Be careful to turn this off, as this 
means that beans that use Camel annotations such as 
org.apache.camel.EndpointInject , org.apache.camel.ProducerTemplate , 
org.apache.camel.Produce , org.apache.camel.Consume etc will not be injected 
and in use. Turning this off should only be done if you are sure you do not use 
any of these Camel features. Not all runtimes allow turning t [...]
@@ -58,7 +60,6 @@
     { "name": "camel.main.mdcLoggingKeysPattern", "description": "Sets the 
pattern used for determine which custom MDC keys to propagate during message 
routing when the routing engine continues routing asynchronously for the given 
message. Setting this pattern to will propagate all custom keys. Or setting the 
pattern to foo,bar will propagate any keys starting with either foo or bar. 
Notice that a set of standard Camel MDC keys are always propagated which starts 
with camel. as key name.  [...]
     { "name": "camel.main.messageHistory", "description": "Sets whether 
message history is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.name", "description": "Sets the name of the 
CamelContext.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
-    { "name": "camel.main.packageScanRouteBuilders", "description": "Sets 
package names for scanning for org.apache.camel.builder.RouteBuilder classes as 
candidates to be included. If you are using Spring Boot then its instead 
recommended to use Spring Boots component scanning and annotate your route 
builder classes with Component. In other words only use this for Camel Main in 
standalone mode.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaTy 
[...]
     { "name": "camel.main.producerTemplateCacheSize", "description": "Producer 
template endpoints cache size.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int", "defaultValue": 1000 },
     { "name": "camel.main.routeControllerBackOffDelay", "description": 
"Backoff delay in millis when restarting a route that failed to startup.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"integer", "javaType": "long" },
     { "name": "camel.main.routeControllerBackOffMaxAttempts", "description": 
"Backoff maximum number of attempts to restart a route that failed to startup. 
When this threshold has been exceeded then the controller will give up 
attempting to restart the route, and the route will remain as stopped.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"integer", "javaType": "long" },
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java 
b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
index 764ec0e..b02a103 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java
@@ -830,4 +830,18 @@ public interface ExtendedCamelContext extends CamelContext 
{
      */
     String resolvePropertyPlaceholders(String text, boolean 
keepUnresolvedOptional);
 
+    /**
+     * Package name to use as base (offset) for classpath scanning of custom 
services, type converters, and the likes
+     *
+     * @return the base package name (can bre null if not configured)
+     */
+    String getBasePackageScan();
+
+    /**
+     * Package name to use as base (offset) for classpath scanning of custom 
services, type converters, and the likes
+     *
+     * @param basePackageScan the base package name
+     */
+    void setBasePackageScan(String basePackageScan);
+
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
 
b/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
index 9f5e8d2..79d9007 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
+++ 
b/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
@@ -20,7 +20,7 @@ package org.apache.camel.spi;
  * A {@link org.apache.camel.TypeConverter} which is capable of annotation 
scanning for
  * {@link org.apache.camel.Converter} classes and add these as type converters.
  * <p/>
- * This is using Camel 2.x style and its recommended to migrate to 
@Converter(loader = true) for fast type converter
+ * This is using Camel 2.x style, and it is recommended to migrate to 
@Converter(loader = true) for fast type converter
  * mode.
  */
 public interface AnnotationScanTypeConverters {
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 0ca1b16..4790907 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -275,6 +275,7 @@ public abstract class AbstractCamelContext extends 
BaseService
     private Boolean allowUseOriginalMessage = Boolean.FALSE;
     private Boolean caseInsensitiveHeaders = Boolean.TRUE;
     private Boolean autowiredEnabled = Boolean.TRUE;
+    private String basePackageScan;
     private boolean lightweight;
     private Long delay;
     private ErrorHandlerFactory errorHandlerFactory;
@@ -2766,8 +2767,9 @@ public abstract class AbstractCamelContext extends 
BaseService
         // optimize - before starting routes lets check if event notifications 
is possible
         eventNotificationApplicable = EventHelper.eventsApplicable(this);
 
-        // ensure additional type converters is loaded
-        if (loadTypeConverters && typeConverter instanceof 
AnnotationScanTypeConverters) {
+        // ensure additional type converters is loaded (either if enabled or 
we should use package scanning from the base)
+        boolean load = loadTypeConverters || getBasePackageScan() != null;
+        if (load && typeConverter instanceof AnnotationScanTypeConverters) {
             StartupStep step2 = 
startupStepRecorder.beginStep(CamelContext.class, null, "Scan TypeConverters");
             ((AnnotationScanTypeConverters) 
typeConverter).scanTypeConverters();
             startupStepRecorder.endStep(step2);
@@ -4271,6 +4273,16 @@ public abstract class AbstractCamelContext extends 
BaseService
     }
 
     @Override
+    public String getBasePackageScan() {
+        return basePackageScan;
+    }
+
+    @Override
+    public void setBasePackageScan(String basePackageScan) {
+        this.basePackageScan = basePackageScan;
+    }
+
+    @Override
     public Boolean isDumpRoutes() {
         return dumpRoutes;
     }
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
index e663b1f..127df21 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultCamelBeanPostProcessor.java
@@ -121,6 +121,7 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor, Ca
 
         if (enabled) {
             // do bean binding on simple types first, and then afterwards on 
complex types
+            injectCamelContextPass(bean, beanName);
             injectFirstPass(bean, beanName, type -> !isComplexUserType(type));
             injectSecondPass(bean, beanName, type -> isComplexUserType(type));
         }
@@ -194,6 +195,11 @@ public class DefaultCamelBeanPostProcessor implements 
CamelBeanPostProcessor, Ca
         return true;
     }
 
+    protected void injectCamelContextPass(Object bean, String beanName) {
+        // initial pass to inject CamelContext
+        injectFields(bean, beanName, type -> 
type.isAssignableFrom(CamelContext.class));
+    }
+
     protected void injectFirstPass(Object bean, String beanName, 
Function<Class, Boolean> filter) {
         // on first pass do field and methods first
         injectFields(bean, beanName, filter);
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
index 0130b6c..dc70793 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.CamelBeanPostProcessor;
@@ -33,10 +34,12 @@ import org.apache.camel.support.ObjectHelper;
 public class DefaultInjector implements Injector {
 
     // use the reflection injector
+    private final CamelContext camelContext;
     private final CamelBeanPostProcessor postProcessor;
 
     public DefaultInjector(CamelContext context) {
-        postProcessor = 
context.adapt(ExtendedCamelContext.class).getBeanPostProcessor();
+        this.camelContext = context;
+        this.postProcessor = 
context.adapt(ExtendedCamelContext.class).getBeanPostProcessor();
     }
 
     @Override
@@ -54,6 +57,8 @@ public class DefaultInjector implements Injector {
                 Object obj = fm.invoke(null);
                 answer = type.cast(obj);
             }
+            // inject camel context if needed
+            CamelContextAware.trySetCamelContext(answer, camelContext);
         } catch (Exception e) {
             throw new RuntimeCamelException("Error invoking factory method: " 
+ factoryMethod + " on class: " + type, e);
         }
@@ -63,7 +68,9 @@ public class DefaultInjector implements Injector {
     @Override
     public <T> T newInstance(Class<T> type, boolean postProcessBean) {
         T answer = ObjectHelper.newInstance(type);
-        if (answer != null && postProcessBean) {
+        // inject camel context if needed
+        CamelContextAware.trySetCamelContext(answer, camelContext);
+        if (postProcessBean) {
             try {
                 postProcessor.postProcessBeforeInitialization(answer, 
answer.getClass().getName());
                 postProcessor.postProcessAfterInitialization(answer, 
answer.getClass().getName());
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
index 65ac1a9..3a1dad1 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java
@@ -22,6 +22,7 @@ import java.io.InputStreamReader;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
@@ -65,13 +66,19 @@ import static java.lang.reflect.Modifier.isStatic;
 public class AnnotationTypeConverterLoader implements TypeConverterLoader {
     public static final String META_INF_SERVICES = 
"META-INF/services/org/apache/camel/TypeConverter";
     private static final Logger LOG = 
LoggerFactory.getLogger(AnnotationTypeConverterLoader.class);
-    private static final Charset UTF8 = Charset.forName("UTF-8");
+    private static final Charset UTF8 = StandardCharsets.UTF_8;
     protected PackageScanClassResolver resolver;
     protected Set<Class<?>> visitedClasses = new HashSet<>();
     protected Set<String> visitedURIs = new HashSet<>();
+    private final String basePackage;
 
     public AnnotationTypeConverterLoader(PackageScanClassResolver resolver) {
+        this(resolver, null);
+    }
+
+    public AnnotationTypeConverterLoader(PackageScanClassResolver resolver, 
String basePackage) {
         this.resolver = resolver;
+        this.basePackage = basePackage;
     }
 
     @Override
@@ -117,12 +124,10 @@ public class AnnotationTypeConverterLoader implements 
TypeConverterLoader {
                 LOG.trace("Found converter packages to scan: {}", 
String.join(", ", packageNames));
             }
             Set<Class<?>> scannedClasses = 
resolver.findAnnotated(Converter.class, packageNames);
-            if (scannedClasses.isEmpty()) {
-                throw new TypeConverterLoaderException(
-                        "Cannot find any type converter classes from the 
following packages: " + Arrays.asList(packageNames));
+            if (!scannedClasses.isEmpty()) {
+                LOG.debug("Found {} packages with {} @Converter classes to 
load", packageNames.length, scannedClasses.size());
+                classes.addAll(scannedClasses);
             }
-            LOG.debug("Found {} packages with {} @Converter classes to load", 
packageNames.length, scannedClasses.size());
-            classes.addAll(scannedClasses);
         }
 
         // load all the found classes into the type converter registry
@@ -206,6 +211,10 @@ public class AnnotationTypeConverterLoader implements 
TypeConverterLoader {
      */
     protected String[] findPackageNames() throws IOException {
         Set<String> packages = new HashSet<>();
+        if (basePackage != null) {
+            String[] pks = basePackage.split(",");
+            packages.addAll(Arrays.asList(pks));
+        }
         ClassLoader ccl = Thread.currentThread().getContextClassLoader();
         if (ccl != null) {
             findPackages(packages, ccl);
diff --git 
a/core/camel-base/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
 
b/core/camel-base/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
index a027d7d0..c8a55df 100644
--- 
a/core/camel-base/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
+++ 
b/core/camel-base/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java
@@ -17,9 +17,11 @@
 package org.apache.camel.impl.converter;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.spi.AnnotationScanTypeConverters;
 import org.apache.camel.spi.Injector;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.TypeConverterLoader;
 import org.apache.camel.util.StopWatch;
 import org.apache.camel.util.TimeUtils;
 import org.slf4j.Logger;
@@ -90,7 +92,7 @@ public class DefaultTypeConverter extends 
BaseTypeConverterRegistry implements A
             loadTypeConvertersDone = true;
 
             if (resolver != null) {
-                typeConverterLoaders.add(new 
AnnotationTypeConverterLoader(resolver));
+                typeConverterLoaders.add(createScanTypeConverterLoader());
             }
 
             int fast = typeMappings.size();
@@ -115,4 +117,12 @@ public class DefaultTypeConverter extends 
BaseTypeConverterRegistry implements A
         String time = TimeUtils.printDuration(watch.taken());
         LOG.debug("Scanned {} type converters in {}", typeMappings.size(), 
time);
     }
+
+    /**
+     * Creates the {@link TypeConverterLoader} to use for scanning for type 
converters such as from the classpath.
+     */
+    protected TypeConverterLoader createScanTypeConverterLoader() {
+        String basePackages = camelContext != null ? 
camelContext.adapt(ExtendedCamelContext.class).getBasePackageScan() : null;
+        return new AnnotationTypeConverterLoader(resolver, basePackages);
+    }
 }
diff --git 
a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
 
b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
index af12c3d..d012b1a2 100644
--- 
a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
+++ 
b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java
@@ -35,6 +35,8 @@ public class ExtendedCamelContextConfigurer extends 
org.apache.camel.support.com
         case "AutowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, java.lang.Boolean.class, 
value)); return true;
         case "backlogtracing":
         case "BacklogTracing": target.setBacklogTracing(property(camelContext, 
java.lang.Boolean.class, value)); return true;
+        case "basepackagescan":
+        case "BasePackageScan": 
target.setBasePackageScan(property(camelContext, java.lang.String.class, 
value)); return true;
         case "beanintrospection":
         case "BeanIntrospection": 
target.setBeanIntrospection(property(camelContext, 
org.apache.camel.spi.BeanIntrospection.class, value)); return true;
         case "beanpostprocessor":
@@ -228,6 +230,8 @@ public class ExtendedCamelContextConfigurer extends 
org.apache.camel.support.com
         case "AutowiredEnabled": return java.lang.Boolean.class;
         case "backlogtracing":
         case "BacklogTracing": return java.lang.Boolean.class;
+        case "basepackagescan":
+        case "BasePackageScan": return java.lang.String.class;
         case "beanintrospection":
         case "BeanIntrospection": return 
org.apache.camel.spi.BeanIntrospection.class;
         case "beanpostprocessor":
@@ -422,6 +426,8 @@ public class ExtendedCamelContextConfigurer extends 
org.apache.camel.support.com
         case "AutowiredEnabled": return target.isAutowiredEnabled();
         case "backlogtracing":
         case "BacklogTracing": return target.isBacklogTracing();
+        case "basepackagescan":
+        case "BasePackageScan": return target.getBasePackageScan();
         case "beanintrospection":
         case "BeanIntrospection": return target.getBeanIntrospection();
         case "beanpostprocessor":
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
index 947801b..c78e7c0 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java
@@ -931,6 +931,16 @@ public class LightweightCamelContext implements 
ExtendedCamelContext, CatalogCam
     }
 
     @Override
+    public String getBasePackageScan() {
+        return getExtendedCamelContext().getBasePackageScan();
+    }
+
+    @Override
+    public void setBasePackageScan(String basePackageScan) {
+        getExtendedCamelContext().setBasePackageScan(basePackageScan);
+    }
+
+    @Override
     public Boolean isUseMDCLogging() {
         return delegate.isUseMDCLogging();
     }
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
index 398d92c..191d79c 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java
@@ -200,6 +200,7 @@ public class LightweightRuntimeCamelContext implements 
ExtendedCamelContext, Cat
     private final boolean dumpRoutes;
     private final String mdcLoggingKeysPattern;
     private final boolean useMDCLogging;
+    private final String basePackageScan;
     private final List<Route> routes;
     private final boolean messageHistory;
     private final boolean allowUseOriginalMessage;
@@ -251,6 +252,7 @@ public class LightweightRuntimeCamelContext implements 
ExtendedCamelContext, Cat
         dumpRoutes = context.isDumpRoutes();
         mdcLoggingKeysPattern = context.getMDCLoggingKeysPattern();
         useMDCLogging = context.isUseMDCLogging();
+        basePackageScan = 
context.adapt(ExtendedCamelContext.class).getBasePackageScan();
         messageHistory = context.isMessageHistory();
         allowUseOriginalMessage = context.isAllowUseOriginalMessage();
         logExhaustedMessageBody = context.isLogExhaustedMessageBody();
@@ -1248,6 +1250,16 @@ public class LightweightRuntimeCamelContext implements 
ExtendedCamelContext, Cat
     }
 
     @Override
+    public String getBasePackageScan() {
+        return basePackageScan;
+    }
+
+    @Override
+    public void setBasePackageScan(String basePackageScan) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public Boolean isDumpRoutes() {
         return dumpRoutes;
     }
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index c508310..8ec80c7 100644
--- 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -39,6 +39,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "AutowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
         case "backlogtracing":
         case "BacklogTracing": target.setBacklogTracing(property(camelContext, 
boolean.class, value)); return true;
+        case "basepackagescan":
+        case "BasePackageScan": 
target.setBasePackageScan(property(camelContext, java.lang.String.class, 
value)); return true;
+        case "basepackagescanenabled":
+        case "BasePackageScanEnabled": 
target.setBasePackageScanEnabled(property(camelContext, boolean.class, value)); 
return true;
         case "beanintrospectionextendedstatistics":
         case "BeanIntrospectionExtendedStatistics": 
target.setBeanIntrospectionExtendedStatistics(property(camelContext, 
boolean.class, value)); return true;
         case "beanintrospectionlogginglevel":
@@ -117,8 +121,6 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "MessageHistory": target.setMessageHistory(property(camelContext, 
boolean.class, value)); return true;
         case "name":
         case "Name": target.setName(property(camelContext, 
java.lang.String.class, value)); return true;
-        case "packagescanroutebuilders":
-        case "PackageScanRouteBuilders": 
target.setPackageScanRouteBuilders(property(camelContext, 
java.lang.String.class, value)); return true;
         case "producertemplatecachesize":
         case "ProducerTemplateCacheSize": 
target.setProducerTemplateCacheSize(property(camelContext, int.class, value)); 
return true;
         case "routecontrollerbackoffdelay":
@@ -260,6 +262,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "AutowiredEnabled": return boolean.class;
         case "backlogtracing":
         case "BacklogTracing": return boolean.class;
+        case "basepackagescan":
+        case "BasePackageScan": return java.lang.String.class;
+        case "basepackagescanenabled":
+        case "BasePackageScanEnabled": return boolean.class;
         case "beanintrospectionextendedstatistics":
         case "BeanIntrospectionExtendedStatistics": return boolean.class;
         case "beanintrospectionlogginglevel":
@@ -338,8 +344,6 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "MessageHistory": return boolean.class;
         case "name":
         case "Name": return java.lang.String.class;
-        case "packagescanroutebuilders":
-        case "PackageScanRouteBuilders": return java.lang.String.class;
         case "producertemplatecachesize":
         case "ProducerTemplateCacheSize": return int.class;
         case "routecontrollerbackoffdelay":
@@ -482,6 +486,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "AutowiredEnabled": return target.isAutowiredEnabled();
         case "backlogtracing":
         case "BacklogTracing": return target.isBacklogTracing();
+        case "basepackagescan":
+        case "BasePackageScan": return target.getBasePackageScan();
+        case "basepackagescanenabled":
+        case "BasePackageScanEnabled": return 
target.isBasePackageScanEnabled();
         case "beanintrospectionextendedstatistics":
         case "BeanIntrospectionExtendedStatistics": return 
target.isBeanIntrospectionExtendedStatistics();
         case "beanintrospectionlogginglevel":
@@ -560,8 +568,6 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "MessageHistory": return target.isMessageHistory();
         case "name":
         case "Name": return target.getName();
-        case "packagescanroutebuilders":
-        case "PackageScanRouteBuilders": return 
target.getPackageScanRouteBuilders();
         case "producertemplatecachesize":
         case "ProducerTemplateCacheSize": return 
target.getProducerTemplateCacheSize();
         case "routecontrollerbackoffdelay":
@@ -686,7 +692,7 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
     public Object getCollectionValueType(Object target, String name, boolean 
ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "configurations":
-        case "Configurations": return java.lang.Object.class;
+        case "Configurations": return 
org.apache.camel.main.CamelConfiguration.class;
         case "globaloptions":
         case "GlobalOptions": return java.lang.String.class;
         case "routesbuilders":
diff --git 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index f68a484..0eaab4a 100644
--- 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -19,6 +19,8 @@
     { "name": "camel.main.autoStartup", "description": "Sets whether the 
object should automatically start when Camel starts. Important: Currently only 
routes can be disabled, as CamelContext's are always started. Note: When 
setting auto startup false on CamelContext then that takes precedence and no 
routes are started. You would need to start CamelContext explicit using the 
org.apache.camel.CamelContext.start() method, to start the context, and then 
you would need to start the routes ma [...]
     { "name": "camel.main.autowiredEnabled", "description": "Whether 
autowiring is enabled. This is used for automatic autowiring options (the 
option must be marked as autowired) by looking up in the registry to find if 
there is a single instance of matching type, which then gets configured on the 
component. This can be used for automatic configuring JDBC data sources, JMS 
connection factories, AWS Clients, etc. Default is true.", "sourceType": 
"org.apache.camel.main.DefaultConfiguration [...]
     { "name": "camel.main.backlogTracing", "description": "Sets whether 
backlog tracing is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.main.basePackageScan", "description": "Package name to 
use as base (offset) for classpath scanning of RouteBuilder , and 
org.apache.camel.TypeConverter classes. If you are using Spring Boot then it is 
instead recommended to use Spring Boots component scanning and annotate your 
route builder classes with Component. In other words only use this for Camel 
Main in standalone mode.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", "jav 
[...]
+    { "name": "camel.main.basePackageScanEnabled", "description": "Whether 
base package scan is enabled.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": true },
     { "name": "camel.main.beanIntrospectionExtendedStatistics", "description": 
"Sets whether bean introspection uses extended statistics. The default is 
false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", 
"type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.beanIntrospectionLoggingLevel", "description": "Sets 
the logging level used by bean introspection, logging activity of its usage. 
The default is TRACE.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "object", 
"javaType": "org.apache.camel.LoggingLevel", "enum": [ "ERROR", "WARN", "INFO", 
"DEBUG", "TRACE", "OFF" ] },
     { "name": "camel.main.beanPostProcessorEnabled", "description": "Can be 
used to turn off bean post processing. Be careful to turn this off, as this 
means that beans that use Camel annotations such as 
org.apache.camel.EndpointInject , org.apache.camel.ProducerTemplate , 
org.apache.camel.Produce , org.apache.camel.Consume etc will not be injected 
and in use. Turning this off should only be done if you are sure you do not use 
any of these Camel features. Not all runtimes allow turning t [...]
@@ -58,7 +60,6 @@
     { "name": "camel.main.mdcLoggingKeysPattern", "description": "Sets the 
pattern used for determine which custom MDC keys to propagate during message 
routing when the routing engine continues routing asynchronously for the given 
message. Setting this pattern to will propagate all custom keys. Or setting the 
pattern to foo,bar will propagate any keys starting with either foo or bar. 
Notice that a set of standard Camel MDC keys are always propagated which starts 
with camel. as key name.  [...]
     { "name": "camel.main.messageHistory", "description": "Sets whether 
message history is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.name", "description": "Sets the name of the 
CamelContext.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
-    { "name": "camel.main.packageScanRouteBuilders", "description": "Sets 
package names for scanning for org.apache.camel.builder.RouteBuilder classes as 
candidates to be included. If you are using Spring Boot then its instead 
recommended to use Spring Boots component scanning and annotate your route 
builder classes with Component. In other words only use this for Camel Main in 
standalone mode.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaTy 
[...]
     { "name": "camel.main.producerTemplateCacheSize", "description": "Producer 
template endpoints cache size.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int", "defaultValue": 1000 },
     { "name": "camel.main.routeControllerBackOffDelay", "description": 
"Backoff delay in millis when restarting a route that failed to startup.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"integer", "javaType": "long" },
     { "name": "camel.main.routeControllerBackOffMaxAttempts", "description": 
"Backoff maximum number of attempts to restart a route that failed to startup. 
When this threshold has been exceeded then the controller will give up 
attempting to restart the route, and the route will remain as stopped.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"integer", "javaType": "long" },
diff --git a/core/camel-main/src/main/docs/main.adoc 
b/core/camel-main/src/main/docs/main.adoc
index 1095d85..8774ae8 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -18,7 +18,7 @@ The following tables lists all the options:
 
 // main options: START
 === Camel Main configurations
-The camel.main supports 107 options, which are listed below.
+The camel.main supports 108 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -32,6 +32,8 @@ The camel.main supports 107 options, which are listed below.
 | *camel.main.autoStartup* | Sets whether the object should automatically 
start when Camel starts. Important: Currently only routes can be disabled, as 
CamelContext's are always started. Note: When setting auto startup false on 
CamelContext then that takes precedence and no routes are started. You would 
need to start CamelContext explicit using the 
org.apache.camel.CamelContext.start() method, to start the context, and then 
you would need to start the routes manually using CamelContext.g [...]
 | *camel.main.autowiredEnabled* | Whether autowiring is enabled. This is used 
for automatic autowiring options (the option must be marked as autowired) by 
looking up in the registry to find if there is a single instance of matching 
type, which then gets configured on the component. This can be used for 
automatic configuring JDBC data sources, JMS connection factories, AWS Clients, 
etc. Default is true. | true | boolean
 | *camel.main.backlogTracing* | Sets whether backlog tracing is enabled or 
not. Default is false. | false | boolean
+| *camel.main.basePackageScan* | Package name to use as base (offset) for 
classpath scanning of RouteBuilder , and org.apache.camel.TypeConverter 
classes. If you are using Spring Boot then it is instead recommended to use 
Spring Boots component scanning and annotate your route builder classes with 
Component. In other words only use this for Camel Main in standalone mode. |  | 
String
+| *camel.main.basePackageScan{zwsp}Enabled* | Whether base package scan is 
enabled. | true | boolean
 | *camel.main.beanIntrospection{zwsp}ExtendedStatistics* | Sets whether bean 
introspection uses extended statistics. The default is false. | false | boolean
 | *camel.main.beanIntrospection{zwsp}LoggingLevel* | Sets the logging level 
used by bean introspection, logging activity of its usage. The default is 
TRACE. |  | LoggingLevel
 | *camel.main.beanPostProcessor{zwsp}Enabled* | Can be used to turn off bean 
post processing. Be careful to turn this off, as this means that beans that use 
Camel annotations such as org.apache.camel.EndpointInject , 
org.apache.camel.ProducerTemplate , org.apache.camel.Produce , 
org.apache.camel.Consume etc will not be injected and in use. Turning this off 
should only be done if you are sure you do not use any of these Camel features. 
Not all runtimes allow turning this off (such as came [...]
@@ -71,7 +73,6 @@ The camel.main supports 107 options, which are listed below.
 | *camel.main.mdcLoggingKeys{zwsp}Pattern* | Sets the pattern used for 
determine which custom MDC keys to propagate during message routing when the 
routing engine continues routing asynchronously for the given message. Setting 
this pattern to will propagate all custom keys. Or setting the pattern to 
foo,bar will propagate any keys starting with either foo or bar. Notice that a 
set of standard Camel MDC keys are always propagated which starts with camel. 
as key name. The match rules are a [...]
 | *camel.main.messageHistory* | Sets whether message history is enabled or 
not. Default is false. | false | boolean
 | *camel.main.name* | Sets the name of the CamelContext. |  | String
-| *camel.main.packageScanRoute{zwsp}Builders* | Sets package names for 
scanning for org.apache.camel.builder.RouteBuilder classes as candidates to be 
included. If you are using Spring Boot then its instead recommended to use 
Spring Boots component scanning and annotate your route builder classes with 
Component. In other words only use this for Camel Main in standalone mode. |  | 
String
 | *camel.main.producerTemplate{zwsp}CacheSize* | Producer template endpoints 
cache size. | 1000 | int
 | *camel.main.routeControllerBack{zwsp}OffDelay* | Backoff delay in millis 
when restarting a route that failed to startup. |  | long
 | *camel.main.routeControllerBack{zwsp}OffMaxAttempts* | Backoff maximum 
number of attempts to restart a route that failed to startup. When this 
threshold has been exceeded then the controller will give up attempting to 
restart the route, and the route will remain as stopped. |  | long
@@ -298,6 +299,77 @@ The camel.lra supports 4 options, which are listed below.
 |===
 // main options: END
 
+== Package Scanning
+
+*Available since Camel 3.16*
+
+When running Camel standalone via `camel-main` JAR, then Camel will use 
package scanning to discover:
+
+- Camel routes by discovering `RouteBuilder` classes
+- Camel configuration classes by discovering `CamelConfiguration` classes
+- Camel type converters by discovering classes annotated with `@Converter`
+
+To use package scanning then Camel needs to know the base package to use as 
_offset_. This
+can be specified either with the `camel.main.basePackage` option or via `Main` 
class as shown below:
+
+[source,java]
+----
+package com.foo.acme;
+
+public class MyCoolApplication {
+
+    public static void main(String[] args) {
+        Main main = new Main(MyCoolApplication.class);
+        main.run();
+    }
+
+}
+----
+
+In the example above, then we use `com.foo.acme` as the base package, which is 
done
+by passing in the class in the `Main` constructor. This is similar with how 
Spring Boot does this.
+
+Camel will then scan from the base package and the sub packages.
+
+=== Disabling Package Scanning
+
+Package scanning can be turned off by setting 
`camel.main.basePackageScanEnabled=false`.
+
+There is a little overhead when using package scanning as Camel performs this 
scan during startup.
+
+== Configuring Camel Main applications
+
+You can use _configuration_ classes to configure Camel Main applications from 
Java.
+
+IMPORTANT: In *Camel 3.16* onwards the configuration classes must implement 
the interface `org.apache.camel.main.CamelConfiguration`.
+In previous versions this was not required.
+
+For example to configure a Camel application by creating custom beans you can 
do:
+
+[source,java]
+----
+public class MyConfiguration implements CamelConfiguration {
+
+    public void configure(CamelContext camelContext) throws Exception {
+        // this method is optional and can be omitted
+        // do any kind of configuration here if needed
+    }
+
+    @BindToRegistry
+    public MyBean myAwesomeBean() {
+        MyBean bean = new MyBean();
+        // do something on bean
+        return bean;
+    }
+}
+----
+
+In the configuration class you can also have custom methods that creates 
beans, such as the `myAwesomeBean` method
+that creates the `MyBean` and registers it with the name `myAwesomeBean` 
(defaults to method name).
+
+This is similar to Spring Boot where you can also do this with the Spring Boot 
`@Bean` annotations,
+or in Quarkus/CDI with the `@Produces` annotation.
+
 == Specifying custom beans
 
 Custom beans can be configured in `camel-main` via properties (such as in the 
`application.properties` file).
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 1d68bc6..5c108df 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -52,6 +52,7 @@ import org.apache.camel.spi.AutowiredLifecycleStrategy;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.Language;
+import org.apache.camel.spi.PackageScanClassResolver;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.RouteTemplateParameterSource;
 import org.apache.camel.spi.StartupStepRecorder;
@@ -302,13 +303,40 @@ public abstract class BaseMainSupport extends BaseService 
{
             postProcessor.postProcessAfterInitialization(configuration, 
configuration.getClass().getName());
         }
 
+        // auto-detect camel configurations via base package scanning
+        String basePackage = 
camelContext.adapt(ExtendedCamelContext.class).getBasePackageScan();
+        if (basePackage != null) {
+            PackageScanClassResolver pscr = 
camelContext.adapt(ExtendedCamelContext.class).getPackageScanClassResolver();
+            Set<Class<?>> found = 
pscr.findImplementations(CamelConfiguration.class, basePackage);
+            for (Class<?> clazz : found) {
+                // lets use Camel's injector so the class has some support for 
dependency injection
+                Object config = camelContext.getInjector().newInstance(clazz);
+                if (config instanceof CamelConfiguration) {
+                    LOG.debug("Discovered CamelConfiguration class: {}", 
clazz);
+                    CamelConfiguration cc = (CamelConfiguration) config;
+                    mainConfigurationProperties.addConfiguration(cc);
+                }
+            }
+        }
+
         if (mainConfigurationProperties.getConfigurationClasses() != null) {
             String[] configClasses = 
mainConfigurationProperties.getConfigurationClasses().split(",");
             for (String configClass : configClasses) {
-                Class<?> configClazz = 
camelContext.getClassResolver().resolveClass(configClass);
-                // lets use Camel's injector so the class has some support for 
dependency injection
-                Object config = 
camelContext.getInjector().newInstance(configClazz);
-                mainConfigurationProperties.addConfiguration(config);
+                Class<CamelConfiguration> configClazz
+                        = 
camelContext.getClassResolver().resolveClass(configClass, 
CamelConfiguration.class);
+                // skip main classes
+                boolean mainClass = false;
+                try {
+                    configClazz.getDeclaredMethod("main", String[].class);
+                    mainClass = true;
+                } catch (NoSuchMethodException e) {
+                    // ignore
+                }
+                if (!mainClass) {
+                    // lets use Camel's injector so the class has some support 
for dependency injection
+                    CamelConfiguration config = 
camelContext.getInjector().newInstance(configClazz);
+                    mainConfigurationProperties.addConfiguration(config);
+                }
             }
         }
 
@@ -493,6 +521,16 @@ public abstract class BaseMainSupport extends BaseService {
         }
     }
 
+    protected void configurePackageScan(CamelContext camelContext) {
+        if (mainConfigurationProperties.isBasePackageScanEnabled()) {
+            // only set the base package if enabled
+            
camelContext.adapt(ExtendedCamelContext.class).setBasePackageScan(mainConfigurationProperties.getBasePackageScan());
+            if (mainConfigurationProperties.getBasePackageScan() != null) {
+                LOG.info("Classpath scanning enabled from base package: {}", 
mainConfigurationProperties.getBasePackageScan());
+            }
+        }
+    }
+
     protected void configureRoutes(CamelContext camelContext) throws Exception 
{
         // then configure and add the routes
         RoutesConfigurer configurer = new RoutesConfigurer();
@@ -504,7 +542,10 @@ public abstract class BaseMainSupport extends BaseService {
         
configurer.setBeanPostProcessor(camelContext.adapt(ExtendedCamelContext.class).getBeanPostProcessor());
         
configurer.setRoutesBuilders(mainConfigurationProperties.getRoutesBuilders());
         
configurer.setRoutesBuilderClasses(mainConfigurationProperties.getRoutesBuilderClasses());
-        
configurer.setPackageScanRouteBuilders(mainConfigurationProperties.getPackageScanRouteBuilders());
+        if (mainConfigurationProperties.isBasePackageScanEnabled()) {
+            // only set the base package if enabled
+            
configurer.setBasePackageScan(mainConfigurationProperties.getBasePackageScan());
+        }
         
configurer.setJavaRoutesExcludePattern(mainConfigurationProperties.getJavaRoutesExcludePattern());
         
configurer.setJavaRoutesIncludePattern(mainConfigurationProperties.getJavaRoutesIncludePattern());
         
configurer.setRoutesExcludePattern(mainConfigurationProperties.getRoutesExcludePattern());
@@ -521,6 +562,8 @@ public abstract class BaseMainSupport extends BaseService {
         configurePropertiesService(camelContext);
         // setup startup recorder before building context
         configureStartupRecorder(camelContext);
+        // setup package scan
+        configurePackageScan(camelContext);
 
         // ensure camel context is build
         camelContext.build();
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
 b/core/camel-main/src/main/java/org/apache/camel/main/CamelConfiguration.java
similarity index 57%
copy from 
core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
copy to 
core/camel-main/src/main/java/org/apache/camel/main/CamelConfiguration.java
index 9f5e8d2..0c871bb 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/CamelConfiguration.java
@@ -14,21 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
+package org.apache.camel.main;
+
+import org.apache.camel.CamelContext;
 
 /**
- * A {@link org.apache.camel.TypeConverter} which is capable of annotation 
scanning for
- * {@link org.apache.camel.Converter} classes and add these as type converters.
- * <p/>
- * This is using Camel 2.x style and its recommended to migrate to 
@Converter(loader = true) for fast type converter
- * mode.
+ * Configuration class for Camel Main applications.
  */
-public interface AnnotationScanTypeConverters {
+public interface CamelConfiguration {
+
+    default void configure(CamelContext camelContext) throws Exception {
+    }
 
-    /**
-     * Scan for {@link org.apache.camel.Converter} classes and add those as 
type converters.
-     *
-     * @throws Exception is thrown if error happened
-     */
-    void scanTypeConverters() throws Exception;
 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/Main.java 
b/core/camel-main/src/main/java/org/apache/camel/main/Main.java
index e666bc0..ae367a1 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/Main.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/Main.java
@@ -31,11 +31,33 @@ public class Main extends MainCommandLineSupport {
     protected static Main instance;
     protected final MainRegistry registry = new MainRegistry();
 
+    /**
+     * Camel main application
+     *
+     * It is recommended to use {@link Main#Main(Class)} to specify the main 
class.
+     */
     public Main() {
     }
 
-    public Main(Class<?>... configurationClass) {
-        super(configurationClass);
+    /**
+     * Camel main application
+     *
+     * @param mainClass the main class
+     */
+    public Main(Class<?> mainClass) {
+        configure().withBasePackageScan(mainClass.getPackageName());
+    }
+
+    /**
+     * Camel main application
+     *
+     * @param mainClass            the main class
+     * @param configurationClasses additional camel configuration classes
+     */
+    @SafeVarargs
+    public Main(Class<?> mainClass, Class<CamelConfiguration>... 
configurationClasses) {
+        super(configurationClasses);
+        configure().withBasePackageScan(mainClass.getPackageName());
     }
 
     public static void main(String... args) throws Exception {
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
index 9cf4a41..c8688b8 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
@@ -29,7 +29,8 @@ public abstract class MainCommandLineSupport extends 
MainSupport {
     protected final List<Option> options = new ArrayList<>();
     private volatile boolean initOptionsDone;
 
-    public MainCommandLineSupport(Class... configurationClasses) {
+    @SafeVarargs
+    public MainCommandLineSupport(Class<CamelConfiguration>... 
configurationClasses) {
         super(configurationClasses);
     }
 
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index 445b9e2..b8334b3 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -26,7 +26,7 @@ import org.apache.camel.spi.BootstrapCloseable;
 import org.apache.camel.spi.Configurer;
 
 /**
- * Global configuration for Camel Main to setup context name, stream caching 
and other global configurations.
+ * Global configuration for Camel Main to configure context name, stream 
caching and other global configurations.
  */
 @Configurer(bootstrap = true)
 public class MainConfigurationProperties extends 
DefaultConfigurationProperties<MainConfigurationProperties>
@@ -38,13 +38,14 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     private boolean autoConfigurationFailFast = true;
     private boolean autoConfigurationLogSummary = true;
     private int durationHitExitCode;
-    private String packageScanRouteBuilders;
+    private String basePackageScan;
+    private boolean basePackageScanEnabled = true;
 
     private String routesBuilderClasses;
     private String configurationClasses;
 
     private List<RoutesBuilder> routesBuilders = new ArrayList<>();
-    private List<Object> configurations = new ArrayList<>();
+    private List<CamelConfiguration> configurations = new ArrayList<>();
 
     // extended configuration
     private HealthConfigurationProperties healthConfigurationProperties;
@@ -303,18 +304,30 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
         this.autoConfigurationLogSummary = autoConfigurationLogSummary;
     }
 
-    public String getPackageScanRouteBuilders() {
-        return packageScanRouteBuilders;
+    public String getBasePackageScan() {
+        return basePackageScan;
     }
 
     /**
-     * Sets package names for scanning for {@link 
org.apache.camel.builder.RouteBuilder} classes as candidates to be
-     * included. If you are using Spring Boot then its instead recommended to 
use Spring Boots component scanning and
-     * annotate your route builder classes with `@Component`. In other words 
only use this for Camel Main in standalone
-     * mode.
+     * Package name to use as base (offset) for classpath scanning of {@link 
RouteBuilder}, and
+     * {@link org.apache.camel.TypeConverter} classes.
+     *
+     * If you are using Spring Boot then it is instead recommended to use 
Spring Boots component scanning and annotate
+     * your route builder classes with `@Component`. In other words only use 
this for Camel Main in standalone mode.
      */
-    public void setPackageScanRouteBuilders(String packageScanRouteBuilders) {
-        this.packageScanRouteBuilders = packageScanRouteBuilders;
+    public void setBasePackageScan(String basePackageScan) {
+        this.basePackageScan = basePackageScan;
+    }
+
+    public boolean isBasePackageScanEnabled() {
+        return basePackageScanEnabled;
+    }
+
+    /**
+     * Whether base package scan is enabled.
+     */
+    public void setBasePackageScanEnabled(boolean basePackageScanEnabled) {
+        this.basePackageScanEnabled = basePackageScanEnabled;
     }
 
     public int getDurationHitExitCode() {
@@ -344,15 +357,16 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     }
 
     /**
-     * Add an additional configuration class to the known list of 
configurations classes.
+     * Adds configuration object to the known list of configurations objects.
      */
-    public void addConfigurationClass(Class<?>... configuration) {
+    @SuppressWarnings("unchecked")
+    private void addConfigurationClass(Class<? extends CamelConfiguration>... 
configuration) {
         String existing = configurationClasses;
         if (existing == null) {
             existing = "";
         }
         if (configuration != null) {
-            for (Class clazz : configuration) {
+            for (Class<? extends CamelConfiguration> clazz : configuration) {
                 if (!existing.isEmpty()) {
                     existing = existing + ",";
                 }
@@ -363,20 +377,27 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     }
 
     /**
-     * Add an additional configuration object to the known list of 
configurations objects.
+     * Adds configuration object to the known list of configurations objects.
      */
-    public void addConfiguration(Object configuration) {
+    public void addConfiguration(CamelConfiguration configuration) {
         configurations.add(configuration);
     }
 
-    public List<Object> getConfigurations() {
+    /**
+     * Adds configuration object to the known list of configurations objects.
+     */
+    public void addConfiguration(Class<? extends CamelConfiguration> 
configuration) {
+        addConfigurationClass(configuration);
+    }
+
+    public List<CamelConfiguration> getConfigurations() {
         return configurations;
     }
 
     /**
      * Sets the configuration objects used to configure the camel context.
      */
-    public void setConfigurations(List<Object> configurations) {
+    public void setConfigurations(List<CamelConfiguration> configurations) {
         this.configurations = configurations;
     }
 
@@ -524,48 +545,58 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     }
 
     /**
-     * Sets package names for scanning for {@link 
org.apache.camel.builder.RouteBuilder} classes as candidates to be
-     * included. If you are using Spring Boot then its instead recommended to 
use Spring Boots component scanning and
-     * annotate your route builder classes with `@Component`. In other words 
only use this for Camel Main in standalone
-     * mode.
+     * Package name to use as base (offset) for classpath scanning of {@link 
RouteBuilder}, and
+     * {@link org.apache.camel.TypeConverter} classes.
+     *
+     * If you are using Spring Boot then it is instead recommended to use 
Spring Boots component scanning and annotate
+     * your route builder classes with `@Component`. In other words only use 
this for Camel Main in standalone mode.
      */
-    public MainConfigurationProperties withPackageScanRouteBuilders(String 
packageScanRouteBuilders) {
-        this.packageScanRouteBuilders = packageScanRouteBuilders;
+    public MainConfigurationProperties withBasePackageScan(String 
basePackageScan) {
+        this.basePackageScan = basePackageScan;
         return this;
     }
 
-    // fluent builders - configurations
-    // --------------------------------------------------------------
-
     /**
-     * Sets classes names that will be used to configure the camel context as 
example by providing custom beans through
-     * {@link org.apache.camel.BindToRegistry} annotation.
+     * Whether base package scan is enabled.
      */
-    public MainConfigurationProperties withConfigurationClasses(String 
configurations) {
-        setConfigurationClasses(configurations);
+    public MainConfigurationProperties withBasePackageScanEnabled(boolean 
basePackageScanEnabled) {
+        this.basePackageScanEnabled = basePackageScanEnabled;
         return this;
     }
 
+    // fluent builders - configurations
+    // --------------------------------------------------------------
+
     /**
-     * Add an additional configuration class to the known list of 
configurations classes.
+     * Adds classes names that will be used to configure the camel context as 
example by providing custom beans through
+     * {@link org.apache.camel.BindToRegistry} annotation.
      */
-    public MainConfigurationProperties 
withAdditionalConfigurationClasses(Class... configuration) {
-        addConfigurationClass(configuration);
+    public MainConfigurationProperties withConfigurations(String 
configurations) {
+        if (this.configurationClasses == null) {
+            this.configurationClasses = "";
+        }
+        if (this.configurationClasses.isEmpty()) {
+            this.configurationClasses = configurations;
+        } else {
+            this.configurationClasses = "," + configurations;
+        }
         return this;
     }
 
     /**
-     * Add an additional configuration object to the known list of 
configurations objects.
+     * Adds a configuration class to the known list of configurations classes.
      */
-    public MainConfigurationProperties withAdditionalConfiguration(Object 
configuration) {
-        addConfiguration(configuration);
+    @SuppressWarnings("unchecked")
+    public MainConfigurationProperties withConfigurations(
+            Class<? extends CamelConfiguration>... configuration) {
+        addConfigurationClass(configuration);
         return this;
     }
 
     /**
      * Sets the configuration objects used to configure the camel context.
      */
-    public MainConfigurationProperties withConfigurations(List<Object> 
configurations) {
+    public MainConfigurationProperties 
withConfigurations(List<CamelConfiguration> configurations) {
         setConfigurations(configurations);
         return this;
     }
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index 824bfec..820d721 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -48,9 +48,12 @@ public abstract class MainSupport extends BaseMainSupport {
     private int durationHitExitCode;
     private String durationMaxAction = "shutdown";
 
-    protected MainSupport(Class<?>... configurationClasses) {
+    @SafeVarargs
+    protected MainSupport(Class<? extends CamelConfiguration>... 
configurationClasses) {
         this();
-        configure().addConfigurationClass(configurationClasses);
+        for (Class<? extends CamelConfiguration> clazz : configurationClasses) 
{
+            configure().addConfiguration(clazz);
+        }
     }
 
     protected MainSupport() {
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java 
b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
index 1a543b1..d4c1bef 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/RoutesConfigurer.java
@@ -42,7 +42,7 @@ public class RoutesConfigurer {
     private RoutesCollector routesCollector;
     private CamelBeanPostProcessor beanPostProcessor;
     private List<RoutesBuilder> routesBuilders;
-    private String packageScanRouteBuilders;
+    private String basePackageScan;
     private String routesBuilderClasses;
     private String javaRoutesExcludePattern;
     private String javaRoutesIncludePattern;
@@ -57,12 +57,12 @@ public class RoutesConfigurer {
         this.routesBuilders = routesBuilders;
     }
 
-    public String getPackageScanRouteBuilders() {
-        return packageScanRouteBuilders;
+    public String getBasePackageScan() {
+        return basePackageScan;
     }
 
-    public void setPackageScanRouteBuilders(String packageScanRouteBuilders) {
-        this.packageScanRouteBuilders = packageScanRouteBuilders;
+    public void setBasePackageScan(String basePackageScan) {
+        this.basePackageScan = basePackageScan;
     }
 
     public String getRoutesBuilderClasses() {
@@ -148,8 +148,8 @@ public class RoutesConfigurer {
             }
         }
 
-        if (getPackageScanRouteBuilders() != null) {
-            String[] pkgs = getPackageScanRouteBuilders().split(",");
+        if (getBasePackageScan() != null) {
+            String[] pkgs = getBasePackageScan().split(",");
             Set<Class<?>> set = camelContext.adapt(ExtendedCamelContext.class)
                     .getPackageScanClassResolver()
                     .findImplementations(RoutesBuilder.class, pkgs);
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/ContextEventsTest.java 
b/core/camel-main/src/test/java/org/apache/camel/main/ContextEventsTest.java
index 314feb5..734cd7b 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/ContextEventsTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/ContextEventsTest.java
@@ -43,7 +43,7 @@ public class ContextEventsTest {
         assertEquals(1, config.onStop.get());
     }
 
-    public static class MyConfig {
+    public static class MyConfig implements CamelConfiguration {
         final AtomicInteger onInitializing = new AtomicInteger();
         final AtomicInteger onInitialized = new AtomicInteger();
         final AtomicInteger onStart = new AtomicInteger();
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainCustomizerTest.java 
b/core/camel-main/src/test/java/org/apache/camel/main/MainCustomizerTest.java
index c4c8031..07bc162 100644
--- 
a/core/camel-main/src/test/java/org/apache/camel/main/MainCustomizerTest.java
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainCustomizerTest.java
@@ -32,7 +32,7 @@ public class MainCustomizerTest {
         Main main = new Main();
 
         try {
-            main.configure().addConfigurationClass(MyConfiguration.class);
+            main.configure().addConfiguration(MyConfiguration.class);
             main.start();
 
             LogComponent component = 
main.getCamelContext().getComponent("log", LogComponent.class);
@@ -48,7 +48,7 @@ public class MainCustomizerTest {
 
         try {
             main.bind("my-filter", ComponentCustomizer.Policy.none());
-            main.configure().addConfigurationClass(MyConfiguration.class);
+            main.configure().addConfiguration(MyConfiguration.class);
             main.start();
 
             LogComponent component = 
main.getCamelContext().getComponent("log", LogComponent.class);
@@ -65,7 +65,7 @@ public class MainCustomizerTest {
         try {
             main.addInitialProperty("camel.customizer.component.log.enabled", 
"false");
             main.bind("my-filter", ComponentCustomizer.Policy.any());
-            main.configure().addConfigurationClass(MyConfiguration.class);
+            main.configure().addConfiguration(MyConfiguration.class);
             main.start();
 
             LogComponent component = 
main.getCamelContext().getComponent("log", LogComponent.class);
@@ -81,7 +81,7 @@ public class MainCustomizerTest {
     //
     // ****************************
 
-    public static class MyConfiguration {
+    public static class MyConfiguration implements CamelConfiguration {
         @BindToRegistry
         public ComponentCustomizer logCustomizer() {
             return ComponentCustomizer.builder(LogComponent.class)
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderTest.java
index 08aa9c0..fe7ba54 100644
--- 
a/core/camel-main/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderTest.java
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainIoCNewRouteBuilderTest.java
@@ -54,7 +54,7 @@ public class MainIoCNewRouteBuilderTest {
         main.stop();
     }
 
-    public static class MyConfiguration {
+    public static class MyConfiguration implements CamelConfiguration {
 
         @BeanInject
         private CamelContext camel;
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainIoCTest.java 
b/core/camel-main/src/test/java/org/apache/camel/main/MainIoCTest.java
index 7f47049..70881df 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/MainIoCTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainIoCTest.java
@@ -38,7 +38,7 @@ public class MainIoCTest {
         // use configuration class
         Main main = new Main();
         // add the configuration
-        main.configure().addConfigurationClass(MyConfiguration.class);
+        main.configure().withConfigurations(MyConfiguration.class);
         // add as class so we get IoC
         main.configure().addRoutesBuilder(MyRouteBuilder.class);
         // manually bind
@@ -101,7 +101,7 @@ public class MainIoCTest {
         // noop
     }
 
-    public static class MyConfiguration {
+    public static class MyConfiguration implements CamelConfiguration {
 
         @BeanInject
         private CamelContext camel;
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
index 80e6aa4..81c0711 100644
--- 
a/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/MainRoutesCollectorPackageScanTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.main;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -28,7 +29,7 @@ public class MainRoutesCollectorPackageScanTest {
     @Test
     public void testMainRoutesCollector() throws Exception {
         Main main = new Main();
-        
main.configure().withPackageScanRouteBuilders("org.apache.camel.main.scan");
+        main.configure().withBasePackageScan("org.apache.camel.main.scan");
         main.start();
 
         CamelContext camelContext = main.getCamelContext();
@@ -50,6 +51,13 @@ public class MainRoutesCollectorPackageScanTest {
         endpoint2.assertIsSatisfied();
         endpoint3.assertIsSatisfied();
 
+        // camel configuration should be scanned
+        Assertions.assertEquals("true", 
camelContext.getGlobalOption("scanConfigured"));
+
+        // custom type converter should be scanned
+        MyFoo foo = camelContext.getTypeConverter().convertTo(MyFoo.class, 
"Donald");
+        assertEquals("Donald", foo.getName());
+
         main.stop();
     }
 
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
 b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyConverter.java
similarity index 57%
copy from 
core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
copy to 
core/camel-main/src/test/java/org/apache/camel/main/scan/MyConverter.java
index 9f5e8d2..013bd75 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyConverter.java
@@ -14,21 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
+package org.apache.camel.main.scan;
 
-/**
- * A {@link org.apache.camel.TypeConverter} which is capable of annotation 
scanning for
- * {@link org.apache.camel.Converter} classes and add these as type converters.
- * <p/>
- * This is using Camel 2.x style and its recommended to migrate to 
@Converter(loader = true) for fast type converter
- * mode.
- */
-public interface AnnotationScanTypeConverters {
+import org.apache.camel.Converter;
+import org.apache.camel.main.MyFoo;
+
+@Converter
+public final class MyConverter {
+
+    private MyConverter() {
+    }
 
-    /**
-     * Scan for {@link org.apache.camel.Converter} classes and add those as 
type converters.
-     *
-     * @throws Exception is thrown if error happened
-     */
-    void scanTypeConverters() throws Exception;
+    @Converter
+    public static MyFoo toFoo(String name) {
+        return new MyFoo(name);
+    }
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
 
b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanConfiguration.java
similarity index 57%
copy from 
core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
copy to 
core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanConfiguration.java
index 9f5e8d2..ce78a59 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/spi/AnnotationScanTypeConverters.java
+++ 
b/core/camel-main/src/test/java/org/apache/camel/main/scan/MyScanConfiguration.java
@@ -14,21 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spi;
+package org.apache.camel.main.scan;
 
-/**
- * A {@link org.apache.camel.TypeConverter} which is capable of annotation 
scanning for
- * {@link org.apache.camel.Converter} classes and add these as type converters.
- * <p/>
- * This is using Camel 2.x style and its recommended to migrate to 
@Converter(loader = true) for fast type converter
- * mode.
- */
-public interface AnnotationScanTypeConverters {
+import org.apache.camel.CamelContext;
+import org.apache.camel.main.CamelConfiguration;
+import org.junit.jupiter.api.Assertions;
+
+public class MyScanConfiguration implements CamelConfiguration {
+
+    @Override
+    public void configure(CamelContext camelContext) throws Exception {
+        Assertions.assertNotNull(camelContext);
+        camelContext.getGlobalOptions().put("scanConfigured", "true");
+    }
 
-    /**
-     * Scan for {@link org.apache.camel.Converter} classes and add those as 
type converters.
-     *
-     * @throws Exception is thrown if error happened
-     */
-    void scanTypeConverters() throws Exception;
 }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_16.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_16.adoc
new file mode 100644
index 0000000..0de3f0b
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide-3_16.adoc
@@ -0,0 +1,12 @@
+= Apache Camel 3.x Upgrade Guide
+
+This document is for helping you upgrade your Apache Camel application
+from Camel 3.x to 3.y. For example if you are upgrading Camel 3.0 to 3.2, then 
you should follow the guides
+from both 3.0 to 3.1 and 3.1 to 3.2.
+
+== Upgrading Camel 3.15 to 3.16
+
+=== camel-main
+
+The option `camel.main.packageScanRouteBuilders` has been renamed to 
`camel.main.basePackageScan`.
+
diff --git a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide.adoc
index b7dff7f..945f0a2 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-3x-upgrade-guide.adoc
@@ -24,3 +24,4 @@ You can find upgrade guide for each release in the following 
pages:
 - xref:camel-3x-upgrade-guide-3_13.adoc[Upgrade guide 3.12 -> 3.13]
 - xref:camel-3x-upgrade-guide-3_14.adoc[Upgrade guide 3.13 -> 3.14]
 - xref:camel-3x-upgrade-guide-3_15.adoc[Upgrade guide 3.14 -> 3.15]
+- xref:camel-3x-upgrade-guide-3_16.adoc[Upgrade guide 3.15 -> 3.16]

Reply via email to