diff --git a/pom.xml b/pom.xml
index 253b26b609..e741100906 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-commons
- 4.1.0-SNAPSHOT
+ 4.1.0-GH-3441-SNAPSHOT
Spring Data Core
Core Spring concepts underpinning every Spring Data module.
diff --git a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java
index c6063ec0c1..3cd89df7cf 100644
--- a/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java
+++ b/src/main/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactory.java
@@ -71,6 +71,9 @@ public MappingAuditableBeanWrapperFactory(PersistentEntities entities) {
this.entities = entities;
this.metadataCache = new ConcurrentHashMap<>();
+
+ entities
+ .forEach(it -> entities.mapOnContext(it.getType(), (context, entity) -> getMetadata(context, it.getType())));
}
@Override
@@ -82,20 +85,26 @@ public Optional> getBeanWrapperFor(T source) {
return super.getBeanWrapperFor(source);
}
- return entities.mapOnContext(it.getClass(), (context, entity) -> {
+ Class> entityClass = it.getClass();
+ return entities.mapOnContext(entityClass, (context, entity) -> {
- MappingAuditingMetadata metadata = metadataCache.computeIfAbsent(it.getClass(),
- key -> new MappingAuditingMetadata(context, it.getClass()));
+ MappingAuditingMetadata metadata = getMetadata(context, entityClass);
- return Optional.> ofNullable(metadata.isAuditable() //
- ? new MappingMetadataAuditableBeanWrapper<>(getConversionService(), entity.getPropertyPathAccessor(it),
- metadata)
- : null);
+ if (metadata.isAuditable()) {
+ return Optional.> of(new MappingMetadataAuditableBeanWrapper<>(getConversionService(),
+ entity.getPropertyPathAccessor(it), metadata));
+ }
+ return Optional.> empty();
}).orElseGet(() -> super.getBeanWrapperFor(source));
});
}
+ private MappingAuditingMetadata getMetadata(MappingContext, ? extends PersistentProperty>> context,
+ Class> entityClass) {
+ return metadataCache.computeIfAbsent(entityClass, key -> new MappingAuditingMetadata(context, entityClass));
+ }
+
/**
* Captures {@link PersistentProperty} instances equipped with auditing annotations.
*
diff --git a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
index 4fcf225805..764bc9f9a7 100644
--- a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
+++ b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java
@@ -136,7 +136,7 @@ public static PersistentEntities of(MappingContext, ?>... contexts) {
* @return result of the {@link BiFunction}.
*/
public Optional mapOnContext(Class> type,
- BiFunction>, PersistentEntity, ?>, T> combiner) {
+ BiFunction>, PersistentEntity, ?>, @Nullable T> combiner) {
Assert.notNull(type, "Type must not be null");
Assert.notNull(combiner, "Combining BiFunction must not be null");
@@ -144,16 +144,21 @@ public Optional mapOnContext(Class> type,
Collection extends MappingContext, ? extends PersistentProperty>>> mappingContexts = getMappingContexts();
if (mappingContexts.size() == 1) {
- return mappingContexts.stream() //
- .filter(it -> it.getPersistentEntity(type) != null) //
- .map(it -> combiner.apply(it, it.getRequiredPersistentEntity(type))) //
- .findFirst();
+ for (MappingContext, ? extends PersistentProperty>> it : mappingContexts) {
+ if (it.getPersistentEntity(type) != null) {
+ return Optional.ofNullable(combiner.apply(it, it.getRequiredPersistentEntity(type)));
+ }
+ }
+ return Optional.empty();
+ }
+
+ for (MappingContext, ? extends PersistentProperty>> it : mappingContexts) {
+ if (it.hasPersistentEntityFor(type)) {
+ return Optional.ofNullable(combiner.apply(it, it.getRequiredPersistentEntity(type)));
+ }
}
- return mappingContexts.stream() //
- .filter(it -> it.hasPersistentEntityFor(type)) //
- .map(it -> combiner.apply(it, it.getRequiredPersistentEntity(type))) //
- .findFirst();
+ return Optional.empty();
}
/**
diff --git a/src/test/java/org/springframework/data/auditing/IsNewAwareAuditingHandlerUnitTests.java b/src/test/java/org/springframework/data/auditing/IsNewAwareAuditingHandlerUnitTests.java
index a0558968b2..cd361bf936 100755
--- a/src/test/java/org/springframework/data/auditing/IsNewAwareAuditingHandlerUnitTests.java
+++ b/src/test/java/org/springframework/data/auditing/IsNewAwareAuditingHandlerUnitTests.java
@@ -20,12 +20,12 @@
import java.util.Optional;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
+
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mapping.context.SampleMappingContext;
@@ -34,24 +34,18 @@
* Unit test for {@code AuditingHandler}.
*
* @author Oliver Gierke
+ * @author Mark Paluch
* @since 1.5
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class IsNewAwareAuditingHandlerUnitTests extends AuditingHandlerUnitTests {
- SampleMappingContext mappingContext;
-
- @BeforeEach
- void init() {
-
- this.mappingContext = new SampleMappingContext();
- this.mappingContext.getPersistentEntity(AuditedUser.class);
- this.mappingContext.afterPropertiesSet();
- }
-
@Override
protected IsNewAwareAuditingHandler getHandler() {
+ SampleMappingContext mappingContext = new SampleMappingContext();
+ mappingContext.getPersistentEntity(AuditedUser.class);
+ mappingContext.afterPropertiesSet();
return new IsNewAwareAuditingHandler(PersistentEntities.of(mappingContext));
}
diff --git a/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java b/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
index 7c47d526ca..7df681a3fc 100755
--- a/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
@@ -45,12 +45,14 @@
import org.springframework.data.domain.Auditable;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mapping.context.SampleMappingContext;
+import org.springframework.test.util.ReflectionTestUtils;
/**
* Unit tests for {@link MappingAuditableBeanWrapperFactory}.
*
* @author Oliver Gierke
* @author Jens Schauder
+ * @author Mark Paluch
* @since 1.8
*/
class MappingAuditableBeanWrapperFactoryUnitTests {
@@ -69,6 +71,13 @@ void setUp() {
factory = new MappingAuditableBeanWrapperFactory(entities);
}
+ @Test // GH-3441
+ void cacheWarmedWithKnownPersistentEntities() {
+
+ Map, ?> metadataCache = (Map, ?>) ReflectionTestUtils.getField(factory, "metadataCache");
+ assertThat(metadataCache).hasSize(4);
+ }
+
@Test // DATACMNS-365
void discoversAuditingPropertyOnField() {