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

[camel] 01/04: CAMEL-14598: Add ComponentNameResolver to discover components on the classpath.

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

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

commit 2e57fd7f4eadc7f0d6269417ddba8f1bcbdb6a99
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Mar 14 13:04:48 2020 +0100

    CAMEL-14598: Add ComponentNameResolver to discover components on the classpath.
---
 .../org/apache/camel/ExtendedCamelContext.java     | 11 +++++
 .../apache/camel/spi/ComponentNameResolver.java    | 35 ++++++++++++++
 .../camel/spi/PackageScanResourceResolver.java     | 17 +++++++
 .../camel/impl/engine/AbstractCamelContext.java    | 20 ++++++++
 .../impl/engine/DefaultComponentNameResolver.java  | 45 ++++++++++++++++++
 .../engine/DefaultPackageScanResourceResolver.java | 40 ++++++++++------
 .../camel/impl/engine/SimpleCamelContext.java      |  6 +++
 .../camel/impl/lw/ImmutableCamelContext.java       | 11 +++++
 .../impl/lw/RuntimeImmutableCamelContext.java      | 13 ++++++
 .../engine/DefaultComponentNameResolverTest.java   | 54 ++++++++++++++++++++++
 .../org/apache/camel/main/BaseMainSupport.java     |  4 +-
 11 files changed, 241 insertions(+), 15 deletions(-)

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 55f92bb..8b53752 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
@@ -30,6 +30,7 @@ import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.BeanProcessorFactory;
 import org.apache.camel.spi.BeanProxyFactory;
 import org.apache.camel.spi.CamelBeanPostProcessor;
+import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.ConfigurerResolver;
 import org.apache.camel.spi.DataFormatResolver;
@@ -262,6 +263,16 @@ public interface ExtendedCamelContext extends CamelContext {
     void setComponentResolver(ComponentResolver componentResolver);
 
     /**
+     * Gets the {@link ComponentNameResolver} to use.
+     */
+    ComponentNameResolver getComponentNameResolver();
+
+    /**
+     * Sets a custom {@link ComponentNameResolver} to use.
+     */
+    void setComponentNameResolver(ComponentNameResolver componentNameResolver);
+
+    /**
      * Gets the {@link LanguageResolver} to use.
      */
     LanguageResolver getLanguageResolver();
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentNameResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentNameResolver.java
new file mode 100644
index 0000000..8454bdc
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentNameResolver.java
@@ -0,0 +1,35 @@
+/*
+ * 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.spi;
+
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Discovers which components are available on the classpath.
+ */
+public interface ComponentNameResolver {
+
+    /**
+     * Discovers which components are available on the classpath.
+     *
+     * @param camelContext the camel context
+     * @return the component names on the classpath
+     */
+    Set<String> resolveNames(CamelContext camelContext);
+}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java
index 9052255..db0bc0e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/PackageScanResourceResolver.java
@@ -74,4 +74,21 @@ public interface PackageScanResourceResolver extends StaticService {
      */
     Set<InputStream> findResources(String location) throws Exception;
 
+    /**
+     * Finds the resource names from the given location.
+     *
+     * The location can be prefixed with either file: or classpath: to look in either file system or classpath.
+     * By default classpath is assumed if no prefix is specified.
+     *
+     * Wildcards is supported using a ANT pattern style paths, such as classpath:&#42;&#42;/&#42;camel&#42;.xml
+     *
+     * Notice when using wildcards, then there is additional overhead as the classpath is scanned, where
+     * as if you specific the exact name for each XML file is faster as no classpath scanning is needed.
+     *
+     * @param location  the location (support ANT style patterns, eg routes/camel-*.xml)
+     * @return the found resource names, or an empty set if no resources found
+     * @throws Exception can be thrown during scanning for resources.
+     */
+    Set<String> findResourceNames(String location) throws Exception;
+
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index b32bbc6..c8acf1b 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -91,6 +91,7 @@ import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.CamelContextTracker;
 import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.ConfigurerResolver;
 import org.apache.camel.spi.DataFormat;
@@ -246,6 +247,7 @@ public abstract class AbstractCamelContext extends BaseService
     private volatile Injector injector;
     private volatile CamelBeanPostProcessor beanPostProcessor;
     private volatile ComponentResolver componentResolver;
+    private volatile ComponentNameResolver componentNameResolver;
     private volatile LanguageResolver languageResolver;
     private volatile ConfigurerResolver configurerResolver;
     private volatile DataFormatResolver dataFormatResolver;
@@ -1882,6 +1884,21 @@ public abstract class AbstractCamelContext extends BaseService
         this.componentResolver = doAddService(componentResolver);
     }
 
+    public ComponentNameResolver getComponentNameResolver() {
+        if (componentNameResolver == null) {
+            synchronized (lock) {
+                if (componentNameResolver == null) {
+                    setComponentNameResolver(createComponentNameResolver());
+                }
+            }
+        }
+        return componentNameResolver;
+    }
+
+    public void setComponentNameResolver(ComponentNameResolver componentNameResolver) {
+        this.componentNameResolver = doAddService(componentNameResolver);
+    }
+
     public LanguageResolver getLanguageResolver() {
         if (languageResolver == null) {
             synchronized (lock) {
@@ -3497,6 +3514,7 @@ public abstract class AbstractCamelContext extends BaseService
         getFactoryFinderResolver();
         getDefaultFactoryFinder();
         getComponentResolver();
+        getComponentNameResolver();
         getDataFormatResolver();
         getManagementStrategy();
         getHeadersMapFactory();
@@ -4431,6 +4449,8 @@ public abstract class AbstractCamelContext extends BaseService
 
     protected abstract ComponentResolver createComponentResolver();
 
+    protected abstract ComponentNameResolver createComponentNameResolver();
+
     protected abstract Registry createRegistry();
 
     protected abstract UuidGenerator createUuidGenerator();
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentNameResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentNameResolver.java
new file mode 100644
index 0000000..a3189de
--- /dev/null
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentNameResolver.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.engine;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.ComponentNameResolver;
+
+public class DefaultComponentNameResolver implements ComponentNameResolver {
+
+    public static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/component/*";
+
+    @Override
+    public Set<String> resolveNames(CamelContext camelContext) {
+        // remove leading path to only keep name
+        Set<String> sorted = new TreeSet<>();
+
+        try {
+            Set<String> locations = camelContext.adapt(ExtendedCamelContext.class).getPackageScanResourceResolver().findResourceNames(RESOURCE_PATH);
+            locations.forEach(l -> sorted.add(l.substring(l.lastIndexOf('/') + 1)));
+        } catch (Exception e) {
+            throw new RuntimeCamelException(e);
+        }
+
+        return sorted;
+    }
+}
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
index a42355d..f814af6 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java
@@ -34,6 +34,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
+import java.util.stream.Collectors;
 
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.NonManagedService;
@@ -41,6 +42,7 @@ import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.util.AntPathMatcher;
 import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.KeyValueHolder;
 import org.apache.camel.util.ObjectHelper;
 
 /**
@@ -50,9 +52,20 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
 
     private static final AntPathMatcher PATH_MATCHER = AntPathMatcher.INSTANCE;
 
+    @Override
+    public Set<String> findResourceNames(String location) throws Exception {
+        Set<KeyValueHolder<String, InputStream>> answer = new LinkedHashSet<>();
+        doFindResources(location, answer);
+        return answer.stream().map(KeyValueHolder::getKey).collect(Collectors.toSet());
+    }
+
     public Set<InputStream> findResources(String location) throws Exception {
-        Set<InputStream> answer = new LinkedHashSet<>();
+        Set<KeyValueHolder<String, InputStream>> answer = new LinkedHashSet<>();
+        doFindResources(location, answer);
+        return answer.stream().map(KeyValueHolder::getValue).collect(Collectors.toSet());
+    }
 
+    protected void doFindResources(String location, Set<KeyValueHolder<String, InputStream>> resources) throws Exception {
         // if its a pattern then we need to scan its root path and find
         // all matching resources using the sub pattern
         if (PATH_MATCHER.isPattern(location)) {
@@ -63,34 +76,33 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
             if ("file:".equals(scheme)) {
                 // file based scanning
                 root = root.substring(scheme.length());
-                findInFileSystem(new File(root), answer, subPattern);
+                findInFileSystem(new File(root), resources, subPattern);
             } else {
                 if ("classpath:".equals(scheme)) {
                     root = root.substring(scheme.length());
                 }
                 // assume classpath based scan from root path and find all resources
-                findInClasspath(root, answer, subPattern);
+                findInClasspath(root, resources, subPattern);
             }
         } else {
             // its a single resource so load it directly
             InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), location);
-            answer.add(is);
+            resources.add(new KeyValueHolder<>(location, is));
         }
-
-        return answer;
     }
 
-    protected void findInFileSystem(File dir, Set<InputStream> resources, String subPattern) throws Exception {
+    protected void findInFileSystem(File dir, Set<KeyValueHolder<String, InputStream>> resources, String subPattern) throws Exception {
         ResourceHelper.findInFileSystem(dir.toPath(), subPattern).forEach(f -> {
             try {
-                resources.add(Files.newInputStream(f));
+                String location = f.toString();
+                resources.add(new KeyValueHolder<>(location, Files.newInputStream(f)));
             } catch (IOException e) {
                 // ignore
             }
         });
     }
 
-    protected void findInClasspath(String packageName, Set<InputStream> resources, String subPattern) {
+    protected void findInClasspath(String packageName, Set<KeyValueHolder<String, InputStream>> resources, String subPattern) {
         packageName = packageName.replace('.', '/');
         // If the URL is a jar, the URLClassloader.getResources() seems to require a trailing slash.
         // The trailing slash is harmless for other URLs
@@ -105,7 +117,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
         }
     }
 
-    protected void doFind(String packageName, ClassLoader classLoader, Set<InputStream> resources, String subPattern) {
+    protected void doFind(String packageName, ClassLoader classLoader, Set<KeyValueHolder<String, InputStream>> resources, String subPattern) {
         Enumeration<URL> urls;
         try {
             urls = getResources(classLoader, packageName);
@@ -207,7 +219,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
      * @param urlPath the url of the jar file to be examined for classes
      */
     private void loadImplementationsInJar(String packageName, String subPattern, InputStream stream,
-                                          String urlPath, Set<InputStream> resources) {
+                                          String urlPath, Set<KeyValueHolder<String, InputStream>> resources) {
         List<String> entries = new ArrayList<>();
 
         JarInputStream jarStream = null;
@@ -241,7 +253,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
                 // use fqn name to load resource
                 InputStream is = getCamelContext().getClassResolver().loadResourceAsStream(name);
                 if (is != null) {
-                    resources.add(is);
+                    resources.add(new KeyValueHolder<>(name, is));
                 }
             }
         }
@@ -260,7 +272,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
      *                 <i>parent</i> would be <i>org/apache</i>
      * @param location a File object representing a directory
      */
-    private void loadImplementationsInDirectory(String subPattern, String parent, File location, Set<InputStream> resources) throws FileNotFoundException {
+    private void loadImplementationsInDirectory(String subPattern, String parent, File location, Set<KeyValueHolder<String, InputStream>> resources) throws FileNotFoundException {
         File[] files = location.listFiles();
         if (files == null || files.length == 0) {
             return;
@@ -281,7 +293,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver
                 log.debug("Found resource: {} matching pattern: {} -> {}", name, subPattern, match);
                 if (match) {
                     InputStream is = new FileInputStream(file);
-                    resources.add(is);
+                    resources.add(new KeyValueHolder<>(name, is));
                 }
             }
         }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
index db8eed0..e6cd59f 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java
@@ -39,6 +39,7 @@ import org.apache.camel.spi.BeanProxyFactory;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.ConfigurerResolver;
 import org.apache.camel.spi.DataFormatResolver;
@@ -155,6 +156,11 @@ public class SimpleCamelContext extends AbstractCamelContext {
     }
 
     @Override
+    protected ComponentNameResolver createComponentNameResolver() {
+        return new DefaultComponentNameResolver();
+    }
+
+    @Override
     protected Registry createRegistry() {
         return new DefaultRegistry();
     }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/ImmutableCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/ImmutableCamelContext.java
index 71ffe85..5d8368e 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/ImmutableCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/ImmutableCamelContext.java
@@ -69,6 +69,7 @@ import org.apache.camel.spi.BeanRepository;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.ConfigurerResolver;
 import org.apache.camel.spi.DataFormat;
@@ -1166,6 +1167,16 @@ public class ImmutableCamelContext implements ExtendedCamelContext, CatalogCamel
     }
 
     @Override
+    public ComponentNameResolver getComponentNameResolver() {
+        return getExtendedCamelContext().getComponentNameResolver();
+    }
+
+    @Override
+    public void setComponentNameResolver(ComponentNameResolver componentNameResolver) {
+        getExtendedCamelContext().setComponentNameResolver(componentNameResolver);
+    }
+
+    @Override
     public LanguageResolver getLanguageResolver() {
         return getExtendedCamelContext().getLanguageResolver();
     }
diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/RuntimeImmutableCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/RuntimeImmutableCamelContext.java
index d2920b6..0470117 100644
--- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/RuntimeImmutableCamelContext.java
+++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/RuntimeImmutableCamelContext.java
@@ -72,6 +72,7 @@ import org.apache.camel.spi.BeanProxyFactory;
 import org.apache.camel.spi.CamelBeanPostProcessor;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.ComponentNameResolver;
 import org.apache.camel.spi.ComponentResolver;
 import org.apache.camel.spi.ConfigurerResolver;
 import org.apache.camel.spi.DataFormat;
@@ -145,6 +146,7 @@ public class RuntimeImmutableCamelContext implements ExtendedCamelContext, Catal
     private final ModelJAXBContextFactory modelJAXBContextFactory;
     private final RuntimeCamelCatalog camelRuntimeCatalog;
     private final ComponentResolver componentResolver;
+    private final ComponentNameResolver componentNameResolver;
     private final LanguageResolver languageResolver;
     private final DataFormatResolver dataFormatResolver;
     private final UuidGenerator uuidGenerator;
@@ -186,6 +188,7 @@ public class RuntimeImmutableCamelContext implements ExtendedCamelContext, Catal
         routes = Collections.unmodifiableList(context.getRoutes());
         uuidGenerator = context.getUuidGenerator();
         componentResolver = context.adapt(ExtendedCamelContext.class).getComponentResolver();
+        componentNameResolver = context.adapt(ExtendedCamelContext.class).getComponentNameResolver();
         languageResolver = context.adapt(ExtendedCamelContext.class).getLanguageResolver();
         dataFormatResolver = context.adapt(ExtendedCamelContext.class).getDataFormatResolver();
         endpoints = (EndpointRegistry) context.getEndpointRegistry();
@@ -416,6 +419,11 @@ public class RuntimeImmutableCamelContext implements ExtendedCamelContext, Catal
     }
 
     @Override
+    public ComponentNameResolver getComponentNameResolver() {
+        return componentNameResolver;
+    }
+
+    @Override
     public LanguageResolver getLanguageResolver() {
         return languageResolver;
     }
@@ -1414,6 +1422,11 @@ public class RuntimeImmutableCamelContext implements ExtendedCamelContext, Catal
     }
 
     @Override
+    public void setComponentNameResolver(ComponentNameResolver componentResolver) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void setLanguageResolver(LanguageResolver languageResolver) {
         throw new UnsupportedOperationException();
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultComponentNameResolverTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultComponentNameResolverTest.java
new file mode 100644
index 0000000..c6d5216
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultComponentNameResolverTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.engine;
+
+import java.util.Set;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spi.ComponentNameResolver;
+import org.junit.Test;
+
+public class DefaultComponentNameResolverTest extends ContextTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testDefaultComponentNameResolver() throws Exception {
+        context.start();
+
+        ComponentNameResolver resolver = context.adapt(ExtendedCamelContext.class).getComponentNameResolver();
+        assertNotNull(resolver);
+
+        Set<String> names = resolver.resolveNames(context);
+        assertNotNull(names);
+        assertTrue(names.size() > 20);
+
+        assertTrue(names.contains("bean"));
+        assertTrue(names.contains("direct"));
+        assertTrue(names.contains("file"));
+        assertTrue(names.contains("log"));
+        assertTrue(names.contains("mock"));
+        assertTrue(names.contains("vm"));
+        assertTrue(names.contains("xslt"));
+
+        context.stop();
+    }
+}
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 b7782ee..b8114a7 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
@@ -1143,7 +1143,8 @@ public abstract class BaseMainSupport extends BaseService {
                 return;
             }
 
-            Object target = supplier.apply(name);
+
+
             String prefix = dot == -1 ? "" : key.substring(0, dot + 1);
             String option = dot == -1 ? "" : key.substring(dot + 1);
             String value = prop.getProperty(key, "");
@@ -1155,6 +1156,7 @@ public abstract class BaseMainSupport extends BaseService {
 
             validateOptionAndValue(key, option, value);
 
+            Object target = supplier.apply(name);
             PropertyOptionKey pok = new PropertyOptionKey(target, prefix);
             Map<String, Object> values = properties.computeIfAbsent(pok, k -> new LinkedHashMap<>());