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 <[email protected]>
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);