From dc7a9a442efc0232291dfbc2dc4121846459cafd Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 4 Nov 2013 11:29:31 +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 c39bf4dcc..8cea743b2 100644 --- a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java +++ b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java @@ -122,7 +122,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 d783f8845..2dbebe787 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; /** @@ -171,6 +173,24 @@ public class AbstractMappingContextUnitTests { assertThat(propertyEntity.getType(), is(equalTo((Class) Person.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; }