Browse Source

DATAMONGO-2586 - Polishing.

Add tests to ensure no reactive auditing callback is registered when using imperative configuration and vice versa.
Update wording and minor code style tweaks.

Original Pull Request: #877
pull/878/head
Christoph Strobl 6 years ago
parent
commit
a8a364c2de
  1. 15
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java
  2. 40
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java
  3. 19
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java
  4. 7
      src/main/asciidoc/reference/mongo-auditing.adoc

15
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2020 the original author or authors. * Copyright 2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,8 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Mark Paluch * @author Mark Paluch
* @author Christoph Strobl
* @since 3.1
*/ */
class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> { class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
@ -44,7 +46,7 @@ class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
* @see org.springframework.beans.factory.FactoryBean#getObject() * @see org.springframework.beans.factory.FactoryBean#getObject()
*/ */
@Override @Override
public PersistentEntities getObject() throws Exception { public PersistentEntities getObject() {
return PersistentEntities.of(converter.getMappingContext()); return PersistentEntities.of(converter.getMappingContext());
} }
@ -56,13 +58,4 @@ class PersistentEntitiesFactoryBean implements FactoryBean<PersistentEntities> {
public Class<?> getObjectType() { public Class<?> getObjectType() {
return PersistentEntities.class; return PersistentEntities.class;
} }
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
@Override
public boolean isSingleton() {
return true;
}
} }

40
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java

@ -21,6 +21,7 @@ import static org.mockito.Mockito.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@ -34,12 +35,16 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.FilterType;
import org.springframework.core.ResolvableType;
import org.springframework.data.annotation.Version; import org.springframework.data.annotation.Version;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mongodb.core.AuditablePerson; import org.springframework.data.mongodb.core.AuditablePerson;
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback;
import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.Client;
@ -48,6 +53,7 @@ import org.springframework.data.mongodb.test.util.MongoTestUtils;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClient;
@ -60,7 +66,7 @@ import com.mongodb.client.MongoClient;
*/ */
@ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ExtendWith({ MongoClientExtension.class, SpringExtension.class })
@ContextConfiguration @ContextConfiguration
public class AuditingViaJavaConfigRepositoriesTests { class AuditingViaJavaConfigRepositoriesTests {
static @Client MongoClient mongoClient; static @Client MongoClient mongoClient;
@ -79,6 +85,7 @@ public class AuditingViaJavaConfigRepositoriesTests {
@Override @Override
protected String getDatabaseName() { protected String getDatabaseName() {
return "database"; return "database";
} }
@ -101,13 +108,13 @@ public class AuditingViaJavaConfigRepositoriesTests {
} }
@BeforeEach @BeforeEach
public void setup() { void setup() {
auditablePersonRepository.deleteAll(); auditablePersonRepository.deleteAll();
this.auditor = auditablePersonRepository.save(new AuditablePerson("auditor")); this.auditor = auditablePersonRepository.save(new AuditablePerson("auditor"));
} }
@Test // DATAMONGO-792, DATAMONGO-883 @Test // DATAMONGO-792, DATAMONGO-883
public void basicAuditing() { void basicAuditing() {
doReturn(Optional.of(this.auditor)).when(this.auditorAware).getCurrentAuditor(); doReturn(Optional.of(this.auditor)).when(this.auditorAware).getCurrentAuditor();
@ -122,18 +129,18 @@ public class AuditingViaJavaConfigRepositoriesTests {
@Test // DATAMONGO-843 @Test // DATAMONGO-843
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void auditingUsesFallbackMappingContextIfNoneConfiguredWithRepositories() { void auditingUsesFallbackMappingContextIfNoneConfiguredWithRepositories() {
new AnnotationConfigApplicationContext(SimpleConfigWithRepositories.class); new AnnotationConfigApplicationContext(SimpleConfigWithRepositories.class);
} }
@Test // DATAMONGO-843 @Test // DATAMONGO-843
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void auditingUsesFallbackMappingContextIfNoneConfigured() { void auditingUsesFallbackMappingContextIfNoneConfigured() {
new AnnotationConfigApplicationContext(SimpleConfig.class); new AnnotationConfigApplicationContext(SimpleConfig.class);
} }
@Test // DATAMONGO-2139 @Test // DATAMONGO-2139
public void auditingWorksForVersionedEntityWithWrapperVersion() { void auditingWorksForVersionedEntityWithWrapperVersion() {
verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), //
it -> it.version, // it -> it.version, //
@ -143,7 +150,7 @@ public class AuditingViaJavaConfigRepositoriesTests {
} }
@Test // DATAMONGO-2179 @Test // DATAMONGO-2179
public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { void auditingWorksForVersionedEntityBatchWithWrapperVersion() {
verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), //
it -> it.version, // it -> it.version, //
@ -153,7 +160,7 @@ public class AuditingViaJavaConfigRepositoriesTests {
} }
@Test // DATAMONGO-2139 @Test // DATAMONGO-2139
public void auditingWorksForVersionedEntityWithSimpleVersion() { void auditingWorksForVersionedEntityWithSimpleVersion() {
verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), //
it -> it.version, // it -> it.version, //
@ -163,7 +170,7 @@ public class AuditingViaJavaConfigRepositoriesTests {
} }
@Test // DATAMONGO-2139 @Test // DATAMONGO-2139
public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() {
verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), //
it -> it.version, // it -> it.version, //
@ -173,7 +180,7 @@ public class AuditingViaJavaConfigRepositoriesTests {
} }
@Test // DATAMONGO-2139 @Test // DATAMONGO-2139
public void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() {
verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), //
it -> it.version, // it -> it.version, //
@ -182,6 +189,19 @@ public class AuditingViaJavaConfigRepositoriesTests {
0L, 1L, 2L); 0L, 1L, 2L);
} }
@Test // DATAMONGO-2586
void auditingShouldOnlyRegisterImperativeAuditingCallback() {
Object callbacks = ReflectionTestUtils.getField(operations, "entityCallbacks");
Object callbackDiscoverer = ReflectionTestUtils.getField(callbacks, "callbackDiscoverer");
List<EntityCallback<?>> actualCallbacks = ReflectionTestUtils.invokeMethod(callbackDiscoverer, "getEntityCallbacks",
AuditablePerson.class, ResolvableType.forClass(EntityCallback.class));
assertThat(actualCallbacks) //
.hasAtLeastOneElementOfType(AuditingEntityCallback.class) //
.doesNotHaveAnyElementsOfTypes(ReactiveAuditingEntityCallback.class);
}
private <T extends AuditablePerson> void verifyAuditingViaVersionProperty(T instance, private <T extends AuditablePerson> void verifyAuditingViaVersionProperty(T instance,
Function<T, Object> versionExtractor, Function<T, Object> createdDateExtractor, Function<T, T> persister, Function<T, Object> versionExtractor, Function<T, Object> createdDateExtractor, Function<T, T> persister,
Object... expectedValues) { Object... expectedValues) {

19
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java

@ -17,12 +17,18 @@ package org.springframework.data.mongodb.config;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import org.springframework.core.ResolvableType;
import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback;
import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback;
import org.springframework.test.util.ReflectionTestUtils;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.test.StepVerifier; import reactor.test.StepVerifier;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
@ -146,6 +152,19 @@ class ReactiveAuditingTests {
0L, 1L, 2L); 0L, 1L, 2L);
} }
@Test // DATAMONGO-2586
void auditingShouldOnlyRegisterReactiveAuditingCallback() {
Object callbacks = ReflectionTestUtils.getField(operations, "entityCallbacks");
Object callbackDiscoverer = ReflectionTestUtils.getField(callbacks, "callbackDiscoverer");
List<EntityCallback<?>> actualCallbacks = ReflectionTestUtils.invokeMethod(callbackDiscoverer, "getEntityCallbacks",
AuditablePerson.class, ResolvableType.forClass(EntityCallback.class));
assertThat(actualCallbacks) //
.hasAtLeastOneElementOfType(ReactiveAuditingEntityCallback.class) //
.doesNotHaveAnyElementsOfTypes(AuditingEntityCallback.class);
}
private <T extends AuditablePerson> void verifyAuditingViaVersionProperty(T instance, private <T extends AuditablePerson> void verifyAuditingViaVersionProperty(T instance,
Function<T, Object> versionExtractor, Function<T, Object> createdDateExtractor, Function<T, Mono<T>> persister, Function<T, Object> versionExtractor, Function<T, Object> createdDateExtractor, Function<T, Mono<T>> persister,
Object... expectedValues) { Object... expectedValues) {

7
src/main/asciidoc/reference/mongo-auditing.adoc

@ -30,9 +30,10 @@ To activate auditing functionality via XML, add the Spring Data Mongo `auditing`
---- ----
==== ====
If you wish to use auditing with the reactive programming model, then enable auditing through `@EnableReactiveMongoAuditing` To enable auditing, leveraging a reactive programming model, use the `@EnableReactiveMongoAuditing` annotation. +
If you expose a bean of type `ReactiveAuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableReactiveMongoAuditing`.
.Activating auditing using JavaConfig .Activating reactive auditing using JavaConfig
==== ====
[source,java] [source,java]
---- ----
@ -47,5 +48,5 @@ class Config {
} }
---- ----
==== ====
If you expose a bean of type `ReactiveAuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableReactiveMongoAuditing`.

Loading…
Cancel
Save