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 2019/08/08 18:14:16 UTC

[camel] branch master updated: CAMEL-13837: FactoryFinder API should avoid throwing exceptions for n… (#3089)

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


The following commit(s) were added to refs/heads/master by this push:
     new 853d381  CAMEL-13837: FactoryFinder API should avoid throwing exceptions for n… (#3089)
853d381 is described below

commit 853d38130d8d80f087e4ad15115e4bb3df65a79e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Aug 8 20:13:54 2019 +0200

    CAMEL-13837: FactoryFinder API should avoid throwing exceptions for n… (#3089)
    
    CAMEL-13837: FactoryFinder API should avoid throwing exceptions for not found resoucces/classes and use Optional API instead. This avoids many try .. catch ignore exceptions during startup of Camel also.
---
 MIGRATION.md                                       |   2 +
 .../camel/component/file/GenericFileEndpoint.java  |   4 +-
 .../component/properties/PropertiesComponent.java  |   2 +-
 .../reactive/streams/ReactiveStreamsHelper.java    |  11 +-
 .../camel/component/rest/RestApiEndpoint.java      |  12 +-
 .../apache/camel/component/rest/RestEndpoint.java  |   6 +-
 .../java/org/apache/camel/spi/FactoryFinder.java   |  31 +---
 .../impl/converter/BaseTypeConverterRegistry.java  |  52 +++++-
 .../camel/impl/engine/AbstractCamelContext.java    | 181 ++++++++-------------
 .../impl/engine/BeanProcessorFactoryResolver.java  |   4 +-
 .../impl/engine/BeanProxyFactoryResolver.java      |   4 +-
 .../impl/engine/DefaultComponentResolver.java      |   4 +-
 .../impl/engine/DefaultDataFormatResolver.java     |   6 +-
 .../camel/impl/engine/DefaultFactoryFinder.java    | 123 ++++----------
 .../camel/impl/engine/DefaultLanguageResolver.java |   4 +-
 .../camel/impl/engine/DefaultProcessorFactory.java |  14 +-
 .../impl/engine/HeadersMapFactoryResolver.java     |   4 +-
 .../impl/engine/ReactiveExecutorResolver.java      |   4 +-
 .../impl/engine/RestRegistryFactoryResolver.java   |   4 +-
 .../camel/processor/SendDynamicAwareResolver.java  |   4 +-
 .../impl/cloud/ServiceCallProcessorFactory.java    |   2 +-
 .../apache/camel/core/osgi/OsgiFactoryFinder.java  |  14 +-
 .../camel/core/osgi/OsgiFactoryFinderTest.java     |  15 +-
 .../org/apache/camel/impl/DefaultCamelContext.java |   8 +-
 .../cloud/ServiceCallExpressionConfiguration.java  |   2 +-
 .../ServiceCallServiceChooserConfiguration.java    |   2 +-
 .../ServiceCallServiceDiscoveryConfiguration.java  |   2 +-
 .../ServiceCallServiceFilterConfiguration.java     |   2 +-
 ...erviceCallServiceLoadBalancerConfiguration.java |   2 +-
 .../impl/engine/DefaultFactoryFinderTest.java      |  62 ++-----
 30 files changed, 234 insertions(+), 353 deletions(-)

diff --git a/MIGRATION.md b/MIGRATION.md
index 5ad468e..83b705a 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -367,6 +367,8 @@ Removed `TypeConverterAware` as you should instead use `Exchange` as parameter t
 
 The `Component` and `DataFormat` interfaces now extend `Service` as components and data formats should also have service contract to manage their lifecycle. The default base classes already implements these interfaces.
 
+The class `FactoryFinder` has changed its API to use `Optional` as return types instead of throwing checked `FactoryNotFoundException` or `ClassNotFoundException` etc.
+
 #### camel-test
 
 If you are using camel-test and override the `createRegistry` method, for example to register beans from the `JndiRegisty` class, then this is no longer necessary, and instead
diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
index d41ed29..58aa43cf 100644
--- a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
+++ b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
@@ -277,9 +277,7 @@ public abstract class GenericFileEndpoint<T> extends ScheduledPollEndpoint imple
         try {
             FactoryFinder finder = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder("META-INF/services/org/apache/camel/component/");
             log.trace("Using FactoryFinder: {}", finder);
-            factory = finder.findClass(getScheme(), "strategy.factory.", CamelContext.class);
-        } catch (ClassNotFoundException e) {
-            log.trace("'strategy.factory.class' not found", e);
+            factory = finder.findClass(getScheme(), "strategy.factory.", CamelContext.class).orElse(null);
         } catch (IOException e) {
             log.trace("No strategy factory defined in 'META-INF/services/org/apache/camel/component/'", e);
         }
diff --git a/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 1492d62..a97f446 100644
--- a/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++ b/components/camel-properties/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -462,7 +462,7 @@ public class PropertiesComponent extends DefaultComponent implements org.apache.
         // discover any 3rd party properties sources
         try {
             FactoryFinder factoryFinder = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder("META-INF/services/org/apache/camel");
-            Class<?> type = factoryFinder.findClass("properties-source-factory");
+            Class<?> type = factoryFinder.findClass("properties-source-factory").orElse(null);
             if (type != null) {
                 Object obj = getCamelContext().getInjector().newInstance(type, false);
                 if (obj instanceof PropertiesSource) {
diff --git a/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsHelper.java b/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsHelper.java
index 40f7b54..a380934 100644
--- a/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsHelper.java
+++ b/components/camel-reactive-streams/src/main/java/org/apache/camel/component/reactive/streams/ReactiveStreamsHelper.java
@@ -114,11 +114,12 @@ public final class ReactiveStreamsHelper {
     public static CamelReactiveStreamsServiceFactory resolveServiceFactory(CamelContext context, String serviceType) {
         try {
             FactoryFinder finder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(ReactiveStreamsConstants.SERVICE_PATH);
-            Class<?> serviceClass = finder.findClass(serviceType);
-
-            return (CamelReactiveStreamsServiceFactory)context.getInjector().newInstance(serviceClass);
-        } catch (ClassNotFoundException e) {
-            throw new IllegalStateException("Class referenced in '" + ReactiveStreamsConstants.SERVICE_PATH + serviceType + "' not found", e);
+            Class<?> serviceClass = finder.findClass(serviceType).orElse(null);
+            if (serviceClass != null) {
+                return (CamelReactiveStreamsServiceFactory) context.getInjector().newInstance(serviceClass);
+            } else {
+                throw new IllegalStateException("Class referenced in '" + ReactiveStreamsConstants.SERVICE_PATH + serviceType + "' not found");
+            }
         } catch (Exception e) {
             throw new IllegalStateException("Unable to create the reactive stream service defined in '" + ReactiveStreamsConstants.SERVICE_PATH + serviceType + "'", e);
         }
diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java
index 4ec16ce..b393aa7 100644
--- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java
+++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.rest;
 
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 import org.apache.camel.Component;
@@ -147,15 +148,8 @@ public class RestApiEndpoint extends DefaultEndpoint {
             if (name == null) {
                 name = DEFAULT_API_COMPONENT_NAME;
             }
-            try {
-                FactoryFinder finder = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
-                Object instance = finder.newInstance(name);
-                if (instance instanceof RestApiProcessorFactory) {
-                    factory = (RestApiProcessorFactory) instance;
-                }
-            } catch (NoFactoryAvailableException e) {
-                // ignore
-            }
+            FactoryFinder finder = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
+            factory = finder.newInstance(name, RestApiProcessorFactory.class).orElse(null);
         }
 
         if (factory != null) {
diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
index 93bed74..d6ab43c 100644
--- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
+++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
@@ -302,11 +302,7 @@ public class RestEndpoint extends DefaultEndpoint {
             // lookup on classpath using factory finder to automatic find it (just add camel-swagger-java to classpath etc)
             try {
                 FactoryFinder finder = getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
-                Object instance = finder.newInstance(DEFAULT_API_COMPONENT_NAME);
-                if (instance instanceof RestProducerFactory) {
-                    // this factory from camel-swagger-java will facade the http component in use
-                    apiDocFactory = (RestProducerFactory) instance;
-                }
+                apiDocFactory = finder.newInstance(DEFAULT_API_COMPONENT_NAME, RestProducerFactory.class).orElse(null);
                 parameters.put("apiDoc", apiDoc);
             } catch (NoFactoryAvailableException e) {
                 throw new IllegalStateException("Cannot find camel-swagger-java on classpath to use with api-doc: " + apiDoc);
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/FactoryFinder.java b/core/camel-api/src/main/java/org/apache/camel/spi/FactoryFinder.java
index 9d98628..a6ba2aa 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/FactoryFinder.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/FactoryFinder.java
@@ -16,10 +16,7 @@
  */
 package org.apache.camel.spi;
 
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.camel.NoFactoryAvailableException;
+import java.util.Optional;
 
 /**
  * Finder to find factories from the resource classpath, usually <b>META-INF/services/org/apache/camel/</b>.
@@ -37,32 +34,26 @@ public interface FactoryFinder {
      * Creates a new class instance using the key to lookup
      *
      * @param key is the key to add to the path to find a text file containing the factory name
-     * @return a newly created instance
-     * @throws org.apache.camel.NoFactoryAvailableException is thrown if no factories exist for the given key
+     * @return a newly created instance (if exists)
      */
-    Object newInstance(String key) throws NoFactoryAvailableException;
+    Optional<Object> newInstance(String key);
 
     /**
      * Creates a new class instance using the key to lookup
      *
      * @param key is the key to add to the path to find a text file containing the factory name
-     * @param injector injector to use
-     * @param type expected type
-     * @return a newly created instance as the expected type
-     * @throws ClassNotFoundException is thrown if not found
-     * @throws java.io.IOException is thrown if loading the class or META-INF file not found
+     * @param type the class type
+     * @return a newly created instance (if exists)
      */
-    <T> List<T> newInstances(String key, Injector injector, Class<T> type) throws ClassNotFoundException, IOException;
+    <T> Optional<T> newInstance(String key, Class<T> type);
 
     /**
      * Finds the given factory class using the key to lookup.
      *
      * @param key is the key to add to the path to find a text file containing the factory name
      * @return the factory class
-     * @throws ClassNotFoundException is thrown if class not found
-     * @throws java.io.IOException is thrown if loading the class or META-INF file not found
      */
-    Class<?> findClass(String key) throws ClassNotFoundException, IOException;
+    Optional<Class<?>> findClass(String key);
 
     /**
      * Finds the given factory class using the key to lookup.
@@ -70,10 +61,8 @@ public interface FactoryFinder {
      * @param key is the key to add to the path to find a text file containing the factory name
      * @param propertyPrefix prefix on key
      * @return the factory class
-     * @throws ClassNotFoundException is thrown if not found
-     * @throws java.io.IOException is thrown if loading the class or META-INF file not found
      */
-    Class<?> findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException;
+    Optional<Class<?>> findClass(String key, String propertyPrefix);
 
     /**
      * Finds the given factory class using the key to lookup.
@@ -82,8 +71,6 @@ public interface FactoryFinder {
      * @param propertyPrefix prefix on key
      * @param clazz the class which is used for checking compatible
      * @return the factory class
-     * @throws ClassNotFoundException is thrown if not found
-     * @throws java.io.IOException is thrown if loading the class or META-INF file not found
      */
-    Class<?> findClass(String key, String propertyPrefix, Class<?> clazz) throws ClassNotFoundException, IOException;
+    Optional<Class<?>> findClass(String key, String propertyPrefix, Class<?> clazz);
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java b/core/camel-base/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
index 8dfce4c..f40b9fd 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
@@ -68,6 +68,7 @@ import org.apache.camel.util.ObjectHelper;
 public abstract class BaseTypeConverterRegistry extends ServiceSupport implements TypeConverter, TypeConverterRegistry {
 
     public static final String META_INF_SERVICES_TYPE_CONVERTER_LOADER = "META-INF/services/org/apache/camel/TypeConverterLoader";
+    public static final String META_INF_SERVICES_FALLBACK_TYPE_CONVERTER = "META-INF/services/org/apache/camel/FallbackTypeConverter";
 
     protected static final TypeConverter MISS_CONVERTER = new TypeConverterSupport() {
         @Override
@@ -587,11 +588,54 @@ public abstract class BaseTypeConverterRegistry extends ServiceSupport implement
         }
     }
 
+    /**
+     * Finds the fallback type converter classes from the classpath looking
+     * for text files on the classpath at the {@link #META_INF_SERVICES_FALLBACK_TYPE_CONVERTER} location.
+     */
+    protected Collection<String> findFallbackTypeConverterClasses() throws IOException {
+        Set<String> loaders = new LinkedHashSet<>();
+        Collection<URL> loaderResources = getFallbackUrls();
+        for (URL url : loaderResources) {
+            log.debug("Loading file {} to retrieve list of fallback type converters, from url: {}", META_INF_SERVICES_FALLBACK_TYPE_CONVERTER, url);
+            BufferedReader reader = IOHelper.buffered(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
+            try {
+                reader.lines()
+                        .map(String::trim)
+                        .filter(l -> !l.isEmpty())
+                        .filter(l -> !l.startsWith("#"))
+                        .forEach(loaders::add);
+            } finally {
+                IOHelper.close(reader, url.toString(), log);
+            }
+        }
+        return loaders;
+    }
+
+    protected Collection<URL> getFallbackUrls() throws IOException {
+        List<URL> loaderResources = new ArrayList<>();
+        for (ClassLoader classLoader : resolver.getClassLoaders()) {
+            Enumeration<URL> resources = classLoader.getResources(META_INF_SERVICES_FALLBACK_TYPE_CONVERTER);
+            while (resources.hasMoreElements()) {
+                URL url = resources.nextElement();
+                loaderResources.add(url);
+            }
+        }
+        return loaderResources;
+    }
+
     protected void loadFallbackTypeConverters() throws IOException, ClassNotFoundException {
-        if (factoryFinder != null) {
-            List<TypeConverter> converters = factoryFinder.newInstances("FallbackTypeConverter", getInjector(), TypeConverter.class);
-            for (TypeConverter converter : converters) {
-                addFallbackTypeConverter(converter, false);
+        Collection<String> names = findFallbackTypeConverterClasses();
+        for (String name : names) {
+            log.debug("Resolving FallbackTypeConverter: {}", name);
+            Class clazz = getResolver().getClassLoaders().stream()
+                    .map(cl -> ObjectHelper.loadClass(name, cl))
+                    .filter(Objects::nonNull)
+                    .findAny().orElseThrow(() -> new ClassNotFoundException(name));
+            Object obj = getInjector().newInstance(clazz, false);
+            if (obj instanceof TypeConverter) {
+                TypeConverter fb = (TypeConverter) obj;
+                log.debug("Adding loaded FallbackTypeConverter: {}", name);
+                addFallbackTypeConverter(fb, false);
             }
         }
     }
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 29e2fdf..15bd973 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
@@ -1499,46 +1499,35 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext
         // component class, which is the location
         // where the documentation exists as well
         FactoryFinder finder = getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(componentName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // component
-            }
-
-            if (clazz == null) {
-                // fallback and find existing component
-                Component existing = hasComponent(componentName);
-                if (existing != null) {
-                    clazz = existing.getClass();
-                } else {
-                    return null;
-                }
+        Class<?> clazz = finder.findClass(componentName).orElse(null);
+        if (clazz == null) {
+            // fallback and find existing component
+            Component existing = hasComponent(componentName);
+            if (existing != null) {
+                clazz = existing.getClass();
+            } else {
+                return null;
             }
+        }
 
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + componentName + ".json";
+        String packageName = clazz.getPackage().getName();
+        packageName = packageName.replace('.', '/');
+        String path = packageName + "/" + componentName + ".json";
 
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading component JSON Schema for: {} using class resolver: {} -> {}", componentName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
-            }
-            // special for ActiveMQ as it is really just JMS
-            if ("ActiveMQComponent".equals(clazz.getSimpleName())) {
-                return getComponentParameterJsonSchema("jms");
-            } else {
-                return null;
+        ClassResolver resolver = getClassResolver();
+        InputStream inputStream = resolver.loadResourceAsStream(path);
+        log.debug("Loading component JSON Schema for: {} using class resolver: {} -> {}", componentName, resolver, inputStream);
+        if (inputStream != null) {
+            try {
+                return IOHelper.loadText(inputStream);
+            } finally {
+                IOHelper.close(inputStream);
             }
-        } catch (ClassNotFoundException e) {
+        }
+        // special for ActiveMQ as it is really just JMS
+        if ("ActiveMQComponent".equals(clazz.getSimpleName())) {
+            return getComponentParameterJsonSchema("jms");
+        } else {
             return null;
         }
     }
@@ -1548,38 +1537,26 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext
         // dataformat class, which is the location
         // where the documentation exists as well
         FactoryFinder finder = getFactoryFinder(DefaultDataFormatResolver.DATAFORMAT_RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(dataFormatName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // data-formats
-            }
-
-            if (clazz == null) {
-                return null;
-            }
+        Class<?> clazz = finder.findClass(dataFormatName).orElse(null);
+        if (clazz == null) {
+            return null;
+        }
 
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + dataFormatName + ".json";
+        String packageName = clazz.getPackage().getName();
+        packageName = packageName.replace('.', '/');
+        String path = packageName + "/" + dataFormatName + ".json";
 
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading dataformat JSON Schema for: {} using class resolver: {} -> {}", dataFormatName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
+        ClassResolver resolver = getClassResolver();
+        InputStream inputStream = resolver.loadResourceAsStream(path);
+        log.debug("Loading dataformat JSON Schema for: {} using class resolver: {} -> {}", dataFormatName, resolver, inputStream);
+        if (inputStream != null) {
+            try {
+                return IOHelper.loadText(inputStream);
+            } finally {
+                IOHelper.close(inputStream);
             }
-            return null;
-
-        } catch (ClassNotFoundException e) {
-            return null;
         }
+        return null;
     }
 
     public String getLanguageParameterJsonSchema(String languageName) throws IOException {
@@ -1587,38 +1564,26 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext
         // language class, which is the location
         // where the documentation exists as well
         FactoryFinder finder = getFactoryFinder(DefaultLanguageResolver.LANGUAGE_RESOURCE_PATH);
-        try {
-            Class<?> clazz = null;
-            try {
-                clazz = finder.findClass(languageName);
-            } catch (NoFactoryAvailableException e) {
-                // ignore, i.e. if a component is an auto-configured spring-boot
-                // languages
-            }
-
-            if (clazz == null) {
-                return null;
-            }
+        Class<?> clazz = finder.findClass(languageName).orElse(null);
+        if (clazz == null) {
+            return null;
+        }
 
-            String packageName = clazz.getPackage().getName();
-            packageName = packageName.replace('.', '/');
-            String path = packageName + "/" + languageName + ".json";
+        String packageName = clazz.getPackage().getName();
+        packageName = packageName.replace('.', '/');
+        String path = packageName + "/" + languageName + ".json";
 
-            ClassResolver resolver = getClassResolver();
-            InputStream inputStream = resolver.loadResourceAsStream(path);
-            log.debug("Loading language JSON Schema for: {} using class resolver: {} -> {}", languageName, resolver, inputStream);
-            if (inputStream != null) {
-                try {
-                    return IOHelper.loadText(inputStream);
-                } finally {
-                    IOHelper.close(inputStream);
-                }
+        ClassResolver resolver = getClassResolver();
+        InputStream inputStream = resolver.loadResourceAsStream(path);
+        log.debug("Loading language JSON Schema for: {} using class resolver: {} -> {}", languageName, resolver, inputStream);
+        if (inputStream != null) {
+            try {
+                return IOHelper.loadText(inputStream);
+            } finally {
+                IOHelper.close(inputStream);
             }
-            return null;
-
-        } catch (ClassNotFoundException e) {
-            return null;
         }
+        return null;
     }
 
     public String getEipParameterJsonSchema(String eipName) throws IOException {
@@ -3444,21 +3409,21 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext
             Object comp = ResolverHelper.lookupComponentInRegistryWithFallback(this, "properties");
             if (comp == null) {
                 try {
-                    Class<?> type = getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH).findClass("properties");
-                    if (type != null) {
-                        log.debug("No existing PropertiesComponent has been configured, creating a new default PropertiesComponent with name: properties");
-                        comp = type.getDeclaredConstructor().newInstance();
-                        globalOptions.put(PropertiesComponent.DEFAULT_CREATED, "true");
-                    }
-                } catch (Exception e) {
-                    throw new IllegalArgumentException("No Component registered for scheme: " + "properties", e);
+                    comp = getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH).newInstance("properties").orElse(null);
+                } catch (NoFactoryAvailableException e) {
+                    // ignore
+                }
+                if (comp != null) {
+                    log.debug("No existing PropertiesComponent has been configured, created a new default PropertiesComponent with name: properties");
+                    globalOptions.put(PropertiesComponent.DEFAULT_CREATED, "true");
                 }
             }
             if (comp instanceof PropertiesComponent) {
-                addComponent("properties", (PropertiesComponent)comp);
+                addComponent("properties", (PropertiesComponent) comp);
+                // this adds comp as properties component and sets this.propertiesComponent = comp
             }
             if (propertiesComponent == null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("Cannot auto create Properties component");
             }
         }
         return propertiesComponent;
@@ -3624,15 +3589,11 @@ public abstract class AbstractCamelContext extends ServiceSupport implements Ext
         if (!isJMXDisabled()) {
             try {
                 FactoryFinder finder = getFactoryFinder("META-INF/services/org/apache/camel/management/");
-                try {
-                    if (finder != null) {
-                        Object object = finder.newInstance("ManagementStrategyFactory");
-                        if (object instanceof ManagementStrategyFactory) {
-                            factory = (ManagementStrategyFactory)object;
-                        }
+                if (finder != null) {
+                    Object object = finder.newInstance("ManagementStrategyFactory").orElse(null);
+                    if (object instanceof ManagementStrategyFactory) {
+                        factory = (ManagementStrategyFactory)object;
                     }
-                } catch (NoFactoryAvailableException e) {
-                    // ignore there is no custom factory
                 }
             } catch (Exception e) {
                 log.warn("Cannot create JMX lifecycle strategy. Will fallback and disable JMX.", e);
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProcessorFactoryResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProcessorFactoryResolver.java
index cc9f375..f0e1c91 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProcessorFactoryResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProcessorFactoryResolver.java
@@ -62,11 +62,11 @@ public class BeanProcessorFactoryResolver {
         return null;
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProxyFactoryResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProxyFactoryResolver.java
index 39405f6..6fda9ed 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProxyFactoryResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/BeanProxyFactoryResolver.java
@@ -62,11 +62,11 @@ public class BeanProxyFactoryResolver {
         return null;
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentResolver.java
index 35f0eaf..cb4484d 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultComponentResolver.java
@@ -76,11 +76,11 @@ public class DefaultComponentResolver implements ComponentResolver {
         }
     }
 
-    private Class<?> findComponent(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findComponent(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
     protected Logger getLog() {
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultDataFormatResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultDataFormatResolver.java
index 1d7f3a9..ed044f1 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultDataFormatResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultDataFormatResolver.java
@@ -67,14 +67,12 @@ public class DefaultDataFormatResolver implements DataFormatResolver {
     private DataFormat createDataFormatFromResource(String name, CamelContext context) {
         DataFormat dataFormat = null;
 
-        Class<?> type = null;
+        Class<?> type;
         try {
             if (dataformatFactory == null) {
                 dataformatFactory = context.adapt(ExtendedCamelContext.class).getFactoryFinder(DATAFORMAT_RESOURCE_PATH);
             }
-            type = dataformatFactory.findClass(name);
-        } catch (NoFactoryAvailableException e) {
-            // ignore
+            type = dataformatFactory.findClass(name).orElse(null);
         } catch (Exception e) {
             throw new IllegalArgumentException("Invalid URI, no DataFormat registered for scheme: " + name, e);
         }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
index d604cfa..ae97d77 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultFactoryFinder.java
@@ -19,19 +19,16 @@ package org.apache.camel.impl.engine;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
 
-import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.FactoryFinder;
-import org.apache.camel.spi.Injector;
-import org.apache.camel.util.CastUtils;
+import org.apache.camel.support.ObjectHelper;
 import org.apache.camel.util.IOHelper;
 
 /**
@@ -54,87 +51,56 @@ public class DefaultFactoryFinder implements FactoryFinder {
     }
 
     @Override
-    public Object newInstance(String key) throws NoFactoryAvailableException {
-        try {
-            return newInstance(key, null);
-        } catch (Exception e) {
-            throw new NoFactoryAvailableException(key, e);
-        }
+    public Optional<Object> newInstance(String key) {
+        return Optional.ofNullable(doNewInstance(key, null));
     }
 
     @Override
-    public <T> List<T> newInstances(String key, Injector injector, Class<T> type) throws ClassNotFoundException, IOException {
-        List<Class<T>> list = CastUtils.cast(findClasses(key));
-        List<T> answer = new ArrayList<>(list.size());
-        answer.add(newInstance(key, injector, type));
-        return answer;
+    public <T> Optional<T> newInstance(String key, Class<T> type) {
+        Object obj = doNewInstance(key, null);
+        return Optional.ofNullable(type.cast(obj));
     }
 
     @Override
-    public Class<?> findClass(String key) throws ClassNotFoundException, IOException {
+    public Optional<Class<?>> findClass(String key) {
         return findClass(key, null);
     }
 
     @Override
-    public Class<?> findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
+    public Optional<Class<?>> findClass(String key, String propertyPrefix) {
         final String prefix = propertyPrefix != null ? propertyPrefix : "";
         final String classKey = prefix + key;
 
-        return addToClassMap(classKey, new ClassSupplier() {
-            @Override
-            public Class<?> get() throws ClassNotFoundException, IOException {
-                return DefaultFactoryFinder.this.newInstance(DefaultFactoryFinder.this.doFindFactoryProperties(key), prefix);
+        Class<?> clazz = addToClassMap(classKey, () -> {
+            Properties prop = doFindFactoryProperties(key);
+            if (prop != null) {
+                return doNewInstance(prop, prefix).orElse(null);
+            } else {
+                return null;
             }
         });
+        return Optional.ofNullable(clazz);
     }
 
     @Override
-    public Class<?> findClass(String key, String propertyPrefix, Class<?> clazz) throws ClassNotFoundException, IOException {
+    public Optional<Class<?>> findClass(String key, String propertyPrefix, Class<?> clazz) {
         // Just ignore clazz which is only useful for OSGiFactoryFinder
         return findClass(key, propertyPrefix);
     }
 
-    private Object newInstance(String key, String propertyPrefix) throws Exception {
-        Class<?> clazz = findClass(key, propertyPrefix);
-        return clazz.getDeclaredConstructor().newInstance();
-    }
-
-    private <T> T newInstance(String key, Injector injector, Class<T> expectedType) throws IOException,
-        ClassNotFoundException {
-        return newInstance(key, injector, null, expectedType);
-    }
-
-    private <T> T newInstance(String key, Injector injector, String propertyPrefix, Class<T> expectedType)
-        throws IOException, ClassNotFoundException {
-        Class<?> type = findClass(key, propertyPrefix);
-        Object value = injector.newInstance(type, false);
-        if (expectedType.isInstance(value)) {
-            return expectedType.cast(value);
-        } else {
-            throw new ClassCastException("Not instanceof " + expectedType.getName() + " value: " + value);
-        }
-    }
-
-    private List<Class<?>> findClasses(String key) throws ClassNotFoundException, IOException {
-        return findClasses(key, null);
+    private Object doNewInstance(String key, String propertyPrefix) {
+        Optional<Class<?>> clazz = findClass(key, propertyPrefix);
+        return clazz.map(ObjectHelper::newInstance).orElse(null);
     }
 
-    private List<Class<?>> findClasses(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
-        Class<?> type = findClass(key, propertyPrefix);
-        return Collections.<Class<?>>singletonList(type);
-    }
-
-    private Class<?> newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException, IOException {
+    private Optional<Class<?>> doNewInstance(Properties properties, String propertyPrefix) throws IOException {
         String className = properties.getProperty(propertyPrefix + "class");
         if (className == null) {
             throw new IOException("Expected property is missing: " + propertyPrefix + "class");
         }
 
         Class<?> clazz = classResolver.resolveClass(className);
-        if (clazz == null) {
-            throw new ClassNotFoundException(className);
-        }
-        return clazz;
+        return Optional.ofNullable(clazz);
     }
 
     private Properties doFindFactoryProperties(String key) throws IOException {
@@ -142,7 +108,7 @@ public class DefaultFactoryFinder implements FactoryFinder {
 
         InputStream in = classResolver.loadResourceAsStream(uri);
         if (in == null) {
-            throw new NoFactoryAvailableException(uri);
+            return null;
         }
 
         // lets load the file
@@ -163,43 +129,22 @@ public class DefaultFactoryFinder implements FactoryFinder {
      * is wrapped by a runtime exception (WrappedRuntimeException) which we catch
      * later on with the only purpose to re-throw the original exception.
      */
-    protected Class<?> addToClassMap(String key, ClassSupplier mappingFunction) throws ClassNotFoundException, IOException {
-        try {
-            return classMap.computeIfAbsent(key, new Function<String, Class<?>>() {
-                @Override
-                public Class<?> apply(String classKey) {
-                    try {
-                        return mappingFunction.get();
-                    } catch (ClassNotFoundException e) {
-                        throw new WrappedRuntimeException(e);
-                    } catch (NoFactoryAvailableException e) {
-                        throw new WrappedRuntimeException(e);
-                    } catch (IOException e) {
-                        throw new WrappedRuntimeException(e);
-                    }
+    protected Class<?> addToClassMap(String key, ClassSupplier mappingFunction) {
+        return classMap.computeIfAbsent(key, new Function<String, Class<?>>() {
+            @Override
+            public Class<?> apply(String classKey) {
+                try {
+                    return mappingFunction.get();
+                } catch (Exception e) {
+                    throw RuntimeCamelException.wrapRuntimeException(e);
                 }
-            });
-        } catch (WrappedRuntimeException e) {
-            if (e.getCause() instanceof ClassNotFoundException) {
-                throw (ClassNotFoundException)e.getCause();
-            } else if (e.getCause() instanceof NoFactoryAvailableException) {
-                throw (NoFactoryAvailableException)e.getCause();
-            } else if (e.getCause() instanceof IOException) {
-                throw (IOException)e.getCause();
-            } else {
-                throw new RuntimeException(e.getCause());
             }
-        }
+        });
     }
 
     @FunctionalInterface
     protected interface ClassSupplier {
-        Class<?> get() throws ClassNotFoundException, IOException;
+        Class<?> get() throws Exception;
     }
 
-    private final class WrappedRuntimeException extends RuntimeException {
-        WrappedRuntimeException(Exception e) {
-            super(e);
-        }
-    }
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultLanguageResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultLanguageResolver.java
index b3c0aa1..61486f5 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultLanguageResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultLanguageResolver.java
@@ -96,14 +96,14 @@ public class DefaultLanguageResolver implements LanguageResolver {
         if (languageFactory == null) {
             languageFactory = context.adapt(ExtendedCamelContext.class).getFactoryFinder(LANGUAGE_RESOURCE_PATH);
         }
-        return languageFactory.findClass(name);
+        return languageFactory.findClass(name).orElse(null);
     }
 
     protected Class<?> findLanguageResolver(String name, CamelContext context) throws Exception {
         if (languageResolver == null) {
             languageResolver = context.adapt(ExtendedCamelContext.class).getFactoryFinder(LANGUAGE_RESOLVER_RESOURCE_PATH);
         }
-        return languageResolver.findClass(name);
+        return languageResolver.findClass(name).orElse(null);
     }
 
     protected Logger getLog() {
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java
index f31e7a2..7be64cb 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/DefaultProcessorFactory.java
@@ -31,6 +31,7 @@ import org.apache.camel.processor.UnitOfWorkProducer;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.ProcessorFactory;
 import org.apache.camel.spi.RouteContext;
+import org.apache.camel.support.ObjectHelper;
 
 /**
  * Default {@link ProcessorFactory} that supports using 3rd party Camel components to implement the EIP {@link Processor}.
@@ -70,16 +71,11 @@ public class DefaultProcessorFactory implements ProcessorFactory {
     public Processor createProcessor(RouteContext routeContext, NamedNode definition) throws Exception {
         String name = definition.getClass().getSimpleName();
         FactoryFinder finder = routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
-        try {
-            if (finder != null) {
-                Object object = finder.newInstance(name);
-                if (object instanceof ProcessorFactory) {
-                    ProcessorFactory pc = (ProcessorFactory) object;
-                    return pc.createProcessor(routeContext, definition);
-                }
+        if (finder != null) {
+            ProcessorFactory pc = finder.newInstance(name, ProcessorFactory.class).orElse(null);
+            if (pc != null) {
+                return pc.createProcessor(routeContext, definition);
             }
-        } catch (NoFactoryAvailableException e) {
-            // ignore there is no custom factory
         }
 
         return null;
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/HeadersMapFactoryResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/HeadersMapFactoryResolver.java
index 0a8e72d..d775765 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/HeadersMapFactoryResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/HeadersMapFactoryResolver.java
@@ -65,11 +65,11 @@ public class HeadersMapFactoryResolver {
         return new DefaultHeadersMapFactory();
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/ReactiveExecutorResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/ReactiveExecutorResolver.java
index b5a2d03..378bc9d 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/ReactiveExecutorResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/ReactiveExecutorResolver.java
@@ -63,11 +63,11 @@ public class ReactiveExecutorResolver {
         return new DefaultReactiveExecutor();
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/engine/RestRegistryFactoryResolver.java b/core/camel-base/src/main/java/org/apache/camel/impl/engine/RestRegistryFactoryResolver.java
index a63263b..162f9e5 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/engine/RestRegistryFactoryResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/engine/RestRegistryFactoryResolver.java
@@ -64,11 +64,11 @@ public class RestRegistryFactoryResolver {
         return null;
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java
index c221bae..6bbefea 100644
--- a/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java
+++ b/core/camel-base/src/main/java/org/apache/camel/processor/SendDynamicAwareResolver.java
@@ -60,11 +60,11 @@ public class SendDynamicAwareResolver {
         return null;
     }
 
-    private Class<?> findFactory(String name, CamelContext context) throws ClassNotFoundException, IOException {
+    private Class<?> findFactory(String name, CamelContext context) throws IOException {
         if (factoryFinder == null) {
             factoryFinder = context.adapt(ExtendedCamelContext.class).getFactoryFinder(RESOURCE_PATH);
         }
-        return factoryFinder.findClass(name);
+        return factoryFinder.findClass(name).orElse(null);
     }
 
 }
diff --git a/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java b/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
index fb4e5b4..0aab58c 100644
--- a/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
+++ b/core/camel-cloud/src/main/java/org/apache/camel/impl/cloud/ServiceCallProcessorFactory.java
@@ -384,7 +384,7 @@ public class ServiceCallProcessorFactory extends TypedProcessorFactory<ServiceCa
 
                 try {
                     // Then use Service factory.
-                    type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(lookupName);
+                    type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(lookupName).orElse(null);
                 } catch (Exception e) {
                 }
 
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
index cb03336..ba57b23 100644
--- a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
@@ -20,9 +20,9 @@ import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Optional;
 import java.util.Properties;
 
-import org.apache.camel.NoFactoryAvailableException;
 import org.apache.camel.impl.engine.DefaultFactoryFinder;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.util.IOHelper;
@@ -44,11 +44,11 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
     }
 
     @Override
-    public Class<?> findClass(String key, String propertyPrefix, Class<?> checkClass) throws ClassNotFoundException, IOException {
+    public Optional<Class<?>> findClass(String key, String propertyPrefix, Class<?> checkClass) {
         final String prefix = propertyPrefix != null ? propertyPrefix : "";
         final String classKey = propertyPrefix + key;
 
-        return addToClassMap(classKey, () -> {
+        Class<?> answer = addToClassMap(classKey, () -> {
             BundleEntry entry = getResource(key, checkClass);
             if (entry != null) {
                 URL url = entry.url;
@@ -69,13 +69,15 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
                     IOHelper.close(in, key, null);
                 }
             } else {
-                throw new NoFactoryAvailableException(classKey);
+                return null;
             }
         });
+
+        return Optional.ofNullable(answer);
     }
 
     @Override
-    public Class<?> findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
+    public Optional<Class<?>> findClass(String key, String propertyPrefix) {
         return findClass(key, propertyPrefix, null);
     }
 
@@ -89,7 +91,7 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
     // The clazz can make sure we get right version of class that we need
     public BundleEntry getResource(String name, Class<?> clazz) {
         BundleEntry entry = null;
-        Bundle[] bundles = null; 
+        Bundle[] bundles;
         
         bundles = bundleContext.getBundles();
         
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java
index e245f44..b8c82f0 100644
--- a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java
@@ -27,21 +27,16 @@ public class OsgiFactoryFinderTest extends CamelOsgiTestSupport {
     @Test
     public void testFindClass() throws Exception {
         OsgiFactoryFinder finder = new OsgiFactoryFinder(getBundleContext(), new DefaultClassResolver(), "META-INF/services/org/apache/camel/component/");
-        Class<?> clazz = finder.findClass("file_test", "strategy.factory.");
+        Class<?> clazz = finder.findClass("file_test", "strategy.factory.").orElse(null);
         assertNotNull("We should get the file strategy factory here", clazz);
         
+        assertFalse(finder.findClass("nofile", "strategy.factory.").isPresent());
+
         try {
-            clazz = finder.findClass("nofile", "strategy.factory.");
-            fail("We should get exception here");
-        } catch (Exception ex) {
-            assertTrue("Should get NoFactoryAvailableException", ex instanceof NoFactoryAvailableException);
-        }
-        
-        try {
-            clazz = finder.findClass("file_test", "nostrategy.factory.");
+            finder.findClass("file_test", "nostrategy.factory.");
             fail("We should get exception here");
         } catch (Exception ex) {
-            assertTrue("Should get IOException", ex instanceof IOException);
+            assertTrue("Should get IOException", ex.getCause() instanceof IOException);
         }
     }
 
diff --git a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 13d5df9..bb79975 100644
--- a/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/core/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -21,7 +21,6 @@ import javax.naming.Context;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
-import org.apache.camel.NoFactoryAvailableException;
 import org.apache.camel.PollingConsumer;
 import org.apache.camel.Producer;
 import org.apache.camel.TypeConverter;
@@ -172,12 +171,7 @@ public class DefaultCamelContext extends AbstractModelCamelContext {
     @Override
     protected Injector createInjector() {
         FactoryFinder finder = getDefaultFactoryFinder();
-        try {
-            return (Injector) finder.newInstance("Injector");
-        } catch (NoFactoryAvailableException e) {
-            // lets use the default injector
-            return new DefaultInjector(this);
-        }
+        return finder.newInstance("Injector", Injector.class).orElse(new DefaultInjector(this));
     }
 
     @Override
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
index 0cd2d61..61ef0d1 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallExpressionConfiguration.java
@@ -228,7 +228,7 @@ public class ServiceCallExpressionConfiguration extends IdentifiedType implement
                 Class<?> type;
                 try {
                     // Then use Service factory.
-                    type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey);
+                    type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey).orElse(null);
                 } catch (Exception e) {
                     throw new NoFactoryAvailableException(ServiceCallDefinitionConstants.RESOURCE_PATH + factoryKey, e);
                 }
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
index b3ff1b6..5b2c2d5 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceChooserConfiguration.java
@@ -146,7 +146,7 @@ public class ServiceCallServiceChooserConfiguration extends IdentifiedType imple
             Class<?> type;
             try {
                 // Then use Service factory.
-                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey);
+                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey).orElse(null);
             } catch (Exception e) {
                 throw new NoFactoryAvailableException(ServiceCallDefinitionConstants.RESOURCE_PATH + factoryKey, e);
             }
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
index f9ad9bd..3203420 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceDiscoveryConfiguration.java
@@ -153,7 +153,7 @@ public class ServiceCallServiceDiscoveryConfiguration extends IdentifiedType imp
             Class<?> type;
             try {
                 // Then use Service factory.
-                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey);
+                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey).orElse(null);
             } catch (Exception e) {
                 throw new NoFactoryAvailableException(ServiceCallDefinitionConstants.RESOURCE_PATH + factoryKey, e);
             }
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
index 7a36a9c..cb14348 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceFilterConfiguration.java
@@ -146,7 +146,7 @@ public class ServiceCallServiceFilterConfiguration extends IdentifiedType implem
             Class<?> type;
             try {
                 // Then use Service factory.
-                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey);
+                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey).orElse(null);
             } catch (Exception e) {
                 throw new NoFactoryAvailableException(ServiceCallDefinitionConstants.RESOURCE_PATH + factoryKey, e);
             }
diff --git a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
index d224f1f..d31fecbb 100644
--- a/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
+++ b/core/camel-core/src/main/java/org/apache/camel/model/cloud/ServiceCallServiceLoadBalancerConfiguration.java
@@ -146,7 +146,7 @@ public class ServiceCallServiceLoadBalancerConfiguration extends IdentifiedType
             Class<?> type;
             try {
                 // Then use Service factory.
-                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey);
+                type = camelContext.adapt(ExtendedCamelContext.class).getFactoryFinder(ServiceCallDefinitionConstants.RESOURCE_PATH).findClass(factoryKey).orElse(null);
             } catch (Exception e) {
                 throw new NoFactoryAvailableException(ServiceCallDefinitionConstants.RESOURCE_PATH + factoryKey, e);
             }
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultFactoryFinderTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultFactoryFinderTest.java
index bdaa0c3..6da11b2 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultFactoryFinderTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultFactoryFinderTest.java
@@ -19,19 +19,16 @@ package org.apache.camel.impl.engine;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.URL;
-import java.util.List;
 
-import org.apache.camel.NoFactoryAvailableException;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.Injector;
 import org.junit.Test;
 
-import static org.hamcrest.Matchers.matchesPattern;
-import static org.hamcrest.core.IsCollectionContaining.hasItem;
 import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -64,13 +61,7 @@ public class DefaultFactoryFinderTest {
 
         final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(classResolver, TEST_RESOURCE_PATH);
 
-        try {
-            factoryFinder.findClass("TestImplA", null);
-            fail("Should have thrown ClassNotFoundException");
-        } catch (final ClassNotFoundException e) {
-            assertEquals(TestImplA.class.getName(), e.getMessage());
-        }
-
+        assertFalse(factoryFinder.findClass("TestImplA", null).isPresent());
     }
 
     @Test
@@ -81,24 +72,16 @@ public class DefaultFactoryFinderTest {
         when(injector.newInstance(TestImplA.class, false)).thenReturn(expected);
 
         try {
-            factoryFinder.newInstances("TestImplA", injector, TestImplB.class);
-            fail("ClassCastException should have been thrown");
-        } catch (final ClassCastException e) {
-            final String message = e.getMessage();
-            assertThat(message,
-                    matchesPattern("Not instanceof org\\.apache\\.camel\\.impl\\.engine\\.DefaultFactoryFinderTest\\$TestImplB "
-                        + "value: org\\.apache\\.camel\\.impl\\.engine\\.DefaultFactoryFinderTest\\$TestImplA.*"));
+            factoryFinder.newInstance("TestImplA", TestImplB.class);
+            fail("Exception should have been thrown");
+        } catch (Exception e) {
+            assertTrue(e instanceof ClassCastException);
         }
     }
 
     @Test
     public void shouldComplainIfUnableToCreateNewInstances() throws ClassNotFoundException, IOException {
-        try {
-            factoryFinder.newInstance("TestImplX");
-            fail("NoFactoryAvailableException should have been thrown");
-        } catch (final NoFactoryAvailableException e) {
-            assertEquals("Cannot find factory class for resource: TestImplX", e.getMessage());
-        }
+        assertFalse(factoryFinder.newInstance("TestImplX").isPresent());
     }
 
     @Test
@@ -106,36 +89,21 @@ public class DefaultFactoryFinderTest {
         try {
             factoryFinder.findClass("TestImplNoProperty");
             fail("NoFactoryAvailableException should have been thrown");
-        } catch (final IOException e) {
-            assertEquals("Expected property is missing: class", e.getMessage());
+        } catch (Exception e) {
+            assertEquals("Expected property is missing: class", e.getCause().getMessage());
         }
     }
 
     @Test
     public void shouldCreateNewInstances() throws ClassNotFoundException, IOException {
-        final Object instance = factoryFinder.newInstance("TestImplA");
+        final Object instance = factoryFinder.newInstance("TestImplA").get();
 
         assertThat(instance, instanceOf(TestImplA.class));
     }
 
     @Test
-    public void shouldCreateNewInstancesWithInjector() throws ClassNotFoundException, IOException {
-        final Injector injector = mock(Injector.class);
-
-        final TestImplA expected = new TestImplA();
-        when(injector.newInstance(TestImplA.class, false)).thenReturn(expected);
-
-        final List<TestType> instances = factoryFinder.newInstances("TestImplA", injector, TestType.class);
-
-        assertEquals(1, instances.size());
-        assertThat(instances, hasItem(expected));
-
-        assertSame(expected, instances.get(0));
-    }
-
-    @Test
     public void shouldFindSingleClass() throws ClassNotFoundException, IOException {
-        final Class<?> clazz = factoryFinder.findClass("TestImplA");
+        final Class<?> clazz = factoryFinder.findClass("TestImplA").orElse(null);
 
         assertEquals(TestImplA.class, clazz);
     }
@@ -145,21 +113,21 @@ public class DefaultFactoryFinderTest {
         final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(null, null);
         factoryFinder.addToClassMap("prefixkey", () -> TestImplA.class);
 
-        final Class<?> clazz = factoryFinder.findClass("key", "prefix");
+        final Class<?> clazz = factoryFinder.findClass("key", "prefix").orElse(null);
 
         assertEquals(TestImplA.class, clazz);
     }
 
     @Test
     public void shouldFindSingleClassWithPropertyPrefix() throws ClassNotFoundException, IOException {
-        final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.");
+        final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.").orElse(null);
 
         assertEquals(TestImplA.class, clazz);
     }
 
     @Test
     public void shouldFindSingleClassWithPropertyPrefixAndExpectedType() throws ClassNotFoundException, IOException {
-        final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.", TestType.class);
+        final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.", TestType.class).orElse(null);
 
         assertEquals(TestImplA.class, clazz);
     }