From d26f90b281e604f7a343b0794c1b3435173f1b5a Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 4 Nov 2013 10:35:19 +0100 Subject: [PATCH] DATACMNS-390 - Create defensive copy for persistent entities in AbstractMappingContext. To prevent ConcurrentModificationExceptions when iterating over PersistentEntities while further entity types are potentially added to the MappingContext we now return a immutable defensive copy of the current entity set. --- .../context/AbstractMappingContext.java | 2 +- .../AbstractMappingContextUnitTests.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java index d940097ed..d1378a5df 100644 --- a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java +++ b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java @@ -124,7 +124,7 @@ public abstract class AbstractMappingContext getPersistentEntities() { try { read.lock(); - return persistentEntities.values(); + return Collections.unmodifiableSet(new HashSet(persistentEntities.values())); } finally { read.unlock(); } diff --git a/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java b/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java index ef71f895e..755ed8f55 100644 --- a/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/context/AbstractMappingContextUnitTests.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import groovy.lang.MetaClass; import java.util.Collections; +import java.util.Iterator; import java.util.List; import org.junit.Before; @@ -34,6 +35,7 @@ import org.springframework.data.mapping.PropertyPath; import org.springframework.data.mapping.model.BasicPersistentEntity; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; /** @@ -193,6 +195,24 @@ public class AbstractMappingContextUnitTests { context.getPersistentPropertyPath("foo", Sample.class); } + /** + * @see DATACMNS-390 + */ + @Test + public void exposesCopyOfPersistentEntitiesToAvoidConcurrentModificationException() { + + SampleMappingContext context = new SampleMappingContext(); + context.getPersistentEntity(ClassTypeInformation.MAP); + + Iterator> iterator = context.getPersistentEntities() + .iterator(); + + while (iterator.hasNext()) { + context.getPersistentEntity(ClassTypeInformation.SET); + iterator.next(); + } + } + class Person { String name; }