diff --git a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java index 52ee2de64..414a7c876 100644 --- a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java @@ -15,6 +15,8 @@ */ package org.springframework.data.convert; +import lombok.Value; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -32,7 +34,7 @@ import org.springframework.util.StringUtils; */ public class SimpleTypeInformationMapper implements TypeInformationMapper { - private final Map> CACHE = new ConcurrentHashMap>(); + private final Map CACHE = new ConcurrentHashMap(); /** * Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint. @@ -55,23 +57,24 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { return null; } - ClassTypeInformation information = CACHE.get(value); + CachedTypeInformation cachedValue = CACHE.get(value); - if (information != null) { - return information; + if (cachedValue != null) { + return cachedValue.getType(); } try { - information = ClassTypeInformation.from(ClassUtils.forName(value, null)); + return cacheAndReturn(value, ClassTypeInformation.from(ClassUtils.forName(value, null))); } catch (ClassNotFoundException e) { - return null; + return cacheAndReturn(value, null); } + } - if (information != null) { - CACHE.put(value, information); - } + private ClassTypeInformation cacheAndReturn(String value, ClassTypeInformation type) { - return information; + CACHE.put(value, CachedTypeInformation.of(type)); + + return type; } /** @@ -84,4 +87,9 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { public String createAliasFor(TypeInformation type) { return type.getType().getName(); } + + @Value(staticConstructor = "of") + static class CachedTypeInformation { + ClassTypeInformation type; + } } diff --git a/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java b/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java index 5454a4489..64845dd8e 100644 --- a/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java +++ b/src/test/java/org/springframework/data/convert/SimpleTypeInformationMapperUnitTests.java @@ -18,9 +18,13 @@ package org.springframework.data.convert; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import java.util.Map; + import org.junit.Test; +import org.springframework.data.convert.SimpleTypeInformationMapper.CachedTypeInformation; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; +import org.springframework.test.util.ReflectionTestUtils; /** * Unit tests for {@link SimpleTypeInformationMapper}. @@ -71,4 +75,20 @@ public class SimpleTypeInformationMapperUnitTests { assertTrue(alias instanceof String); assertThat(alias, is((Object) String.class.getName())); } + + @Test // DATACMNS-1301 + public void cachesFailedAttemptToLoadClass() { + + TypeInformationMapper mapper = new SimpleTypeInformationMapper(); + + assertThat(mapper.resolveTypeFrom("foo"), is(nullValue())); + + Map cache = (Map) ReflectionTestUtils.getField(mapper, + "CACHE"); + + CachedTypeInformation value = cache.get("foo"); + + assertThat(value, is(notNullValue())); + assertThat(value.getType(), is(nullValue())); + } }