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

ggrzybek 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 0c0efc1  [CAMEL-15061] Cache failed attempts to load classes to 
greatly improve performance (#3826)
0c0efc1 is described below

commit 0c0efc1d954a975f04bfb434967ac757600425b2
Author: Grzegorz Grzybek <gr.grzy...@gmail.com>
AuthorDate: Thu May 14 16:29:34 2020 +0200

    [CAMEL-15061] Cache failed attempts to load classes to greatly improve 
performance (#3826)
---
 .../camel/impl/engine/DefaultFactoryFinder.java     | 21 ++++++++++++++++++++-
 .../camel/impl/engine/DefaultFactoryFinderTest.java | 20 ++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

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 d1ecced..bd4f64e 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
@@ -37,6 +37,8 @@ import org.apache.camel.util.IOHelper;
 public class DefaultFactoryFinder implements FactoryFinder {
 
     private final ConcurrentMap<String, Class<?>> classMap = new 
ConcurrentHashMap<>();
+    private final ConcurrentMap<String, Boolean> classesNotFound = new 
ConcurrentHashMap<>();
+    private final ConcurrentMap<String, Exception> classesNotFoundExceptions = 
new ConcurrentHashMap<>();
     private final ClassResolver classResolver;
     private final String path;
 
@@ -135,16 +137,33 @@ public class DefaultFactoryFinder implements 
FactoryFinder {
      * later on with the only purpose to re-throw the original exception.
      */
     protected Class<?> addToClassMap(String key, ClassSupplier 
mappingFunction) {
-        return classMap.computeIfAbsent(key, new Function<String, Class<?>>() {
+        if (classesNotFound.containsKey(key) || 
classesNotFoundExceptions.containsKey(key)) {
+            Exception e = classesNotFoundExceptions.get(key);
+            if (e == null) {
+                return null;
+            } else {
+                throw RuntimeCamelException.wrapRuntimeException(e);
+            }
+        }
+
+        Class<?> suppliedClass = classMap.computeIfAbsent(key, new 
Function<String, Class<?>>() {
             @Override
             public Class<?> apply(String classKey) {
                 try {
                     return mappingFunction.get();
                 } catch (Exception e) {
+                    classesNotFoundExceptions.put(key, e);
                     throw RuntimeCamelException.wrapRuntimeException(e);
                 }
             }
         });
+
+        if (suppliedClass == null) {
+            // mark the key as non-resolvable to prevent pointless searching
+            classesNotFound.put(key, Boolean.TRUE);
+        }
+
+        return suppliedClass;
     }
 
     @FunctionalInterface
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 443b88b..615af00 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
@@ -31,6 +31,8 @@ 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.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class DefaultFactoryFinderTest {
@@ -64,6 +66,24 @@ public class DefaultFactoryFinderTest {
     }
 
     @Test
+    public void shouldCacheFailedAttemptToResolveClass() throws IOException {
+        final ClassResolver classResolver = mock(ClassResolver.class);
+
+        final String properties = "class=" + TestImplA.class.getName();
+
+        
when(classResolver.loadResourceAsStream("/org/apache/camel/impl/TestImplA")).thenReturn(new
 ByteArrayInputStream(properties.getBytes()));
+
+        
when(classResolver.resolveClass(TestImplA.class.getName())).thenReturn(null);
+
+        final DefaultFactoryFinder factoryFinder = new 
DefaultFactoryFinder(classResolver, TEST_RESOURCE_PATH);
+
+        assertFalse(factoryFinder.findClass("TestImplA").isPresent());
+        assertFalse(factoryFinder.findClass("TestImplA").isPresent());
+
+        verify(classResolver, 
times(1)).resolveClass(TestImplA.class.getName());
+    }
+
+    @Test
     public void shouldComplainIfInstanceTypeIsNotAsExpected() throws 
ClassNotFoundException, IOException {
         final Injector injector = mock(Injector.class);
 

Reply via email to