From 81706ba0ed9a3c31c1571b6299543a594b8e0146 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 14 Jul 2020 10:02:52 +0200 Subject: [PATCH 1/2] DATAMONGO-2586 - Prepare issue branch. --- pom.xml | 8 +++++--- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index f50a5f840f..7112632df5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,13 @@ - + 4.0.0 org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-DATAMONGO-2586-SNAPSHOT pom Spring Data MongoDB @@ -26,7 +28,7 @@ multi spring-data-mongodb - 2.4.0-SNAPSHOT + 2.4.0-DATACMNS-1231-SNAPSHOT 4.0.4 ${mongo} 1.19 diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index a85b081e26..919975e850 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-DATAMONGO-2586-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 33014c7c4f..9aa1c48d55 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-DATAMONGO-2586-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ea401d5618..ef480d9840 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.0-SNAPSHOT + 3.1.0-DATAMONGO-2586-SNAPSHOT ../pom.xml From c21747323eac37cef418b168d92d8341a03952de Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 14 Jul 2020 11:23:31 +0200 Subject: [PATCH 2/2] DATAMONGO-2586 - Add support for reactive auditing. We now provide a fully reactive variant for auditing with EnableReactiveMongoAuditing. --- .../mongodb/config/EnableMongoAuditing.java | 4 +- .../config/EnableReactiveMongoAuditing.java | 70 +++++++++++++ .../config/MongoAuditingRegistrar.java | 74 +------------- .../config/PersistentEntitiesFactoryBean.java | 68 +++++++++++++ .../ReactiveMongoAuditingRegistrar.java | 97 +++++++++++++++++++ .../data/mongodb/core/MongoTemplate.java | 2 +- .../event/ReactiveAuditingEntityCallback.java | 13 ++- .../mongodb/config/ReactiveAuditingTests.java | 36 +++---- .../ReactiveMongoTemplateAuditingTests.java | 19 ++-- src/main/asciidoc/new-features.adoc | 5 + .../asciidoc/reference/mongo-auditing.adoc | 19 ++++ 11 files changed, 301 insertions(+), 106 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java index 98bd186da2..e934dc2114 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableMongoAuditing.java @@ -61,8 +61,8 @@ boolean modifyOnCreate() default true; /** - * Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be - * used for setting creation and modification dates. + * Configures a {@link DateTimeProvider} bean name that allows customizing the timestamp to be used for setting + * creation and modification dates. * * @return empty {@link String} by default. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java new file mode 100644 index 0000000000..d7e6b2033e --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/EnableReactiveMongoAuditing.java @@ -0,0 +1,70 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.config; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Import; +import org.springframework.data.auditing.DateTimeProvider; +import org.springframework.data.domain.ReactiveAuditorAware; + +/** + * Annotation to enable auditing in MongoDB using reactive infrastructure via annotation configuration. + * + * @author Mark Paluch + * @since 3.1 + */ +@Inherited +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(ReactiveMongoAuditingRegistrar.class) +public @interface EnableReactiveMongoAuditing { + + /** + * Configures the {@link ReactiveAuditorAware} bean to be used to lookup the current principal. + * + * @return empty {@link String} by default. + */ + String auditorAwareRef() default ""; + + /** + * Configures whether the creation and modification dates are set. Defaults to {@literal true}. + * + * @return {@literal true} by default. + */ + boolean setDates() default true; + + /** + * Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}. + * + * @return {@literal true} by default. + */ + boolean modifyOnCreate() default true; + + /** + * Configures a {@link DateTimeProvider} bean name that allows customizing the timestamp to be used for setting + * creation and modification dates. + * + * @return empty {@link String} by default. + */ + String dateTimeProviderRef() default ""; +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java index f842b9b738..eb6366d2a6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoAuditingRegistrar.java @@ -17,7 +17,6 @@ import java.lang.annotation.Annotation; -import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -28,14 +27,8 @@ import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; import org.springframework.data.auditing.config.AuditingConfiguration; import org.springframework.data.config.ParsingUtils; -import org.springframework.data.mapping.context.MappingContext; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; -import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback; -import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; /** * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableMongoAuditing} annotation. @@ -46,9 +39,6 @@ */ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { - private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono", - MongoAuditingRegistrar.class.getClassLoader()); - /* * (non-Javadoc) * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() @@ -91,7 +81,7 @@ protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingCon BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class); - BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(MongoMappingContextLookup.class); + BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); builder.addConstructorArgValue(definition.getBeanDefinition()); @@ -116,68 +106,6 @@ protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandle registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(), AuditingEntityCallback.class.getName(), registry); - - if (PROJECT_REACTOR_AVAILABLE) { - registerReactiveAuditingEntityCallback(registry, auditingHandlerDefinition.getSource()); - } } - private void registerReactiveAuditingEntityCallback(BeanDefinitionRegistry registry, Object source) { - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class); - - builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)); - builder.getRawBeanDefinition().setSource(source); - - registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(), - registry); - } - - /** - * Simple helper to be able to wire the {@link MappingContext} from a {@link MappingMongoConverter} bean available in - * the application context. - * - * @author Oliver Gierke - */ - static class MongoMappingContextLookup - implements FactoryBean, MongoPersistentProperty>> { - - private final MappingMongoConverter converter; - - /** - * Creates a new {@link MongoMappingContextLookup} for the given {@link MappingMongoConverter}. - * - * @param converter must not be {@literal null}. - */ - public MongoMappingContextLookup(MappingMongoConverter converter) { - this.converter = converter; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObject() - */ - @Override - public MappingContext, MongoPersistentProperty> getObject() throws Exception { - return converter.getMappingContext(); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObjectType() - */ - @Override - public Class getObjectType() { - return MappingContext.class; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#isSingleton() - */ - @Override - public boolean isSingleton() { - return true; - } - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java new file mode 100644 index 0000000000..474559228d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/PersistentEntitiesFactoryBean.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.config; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; + +/** + * Simple helper to be able to wire the {@link PersistentEntities} from a {@link MappingMongoConverter} bean available + * in the application context. + * + * @author Oliver Gierke + * @author Mark Paluch + */ +class PersistentEntitiesFactoryBean implements FactoryBean { + + private final MappingMongoConverter converter; + + /** + * Creates a new {@link PersistentEntitiesFactoryBean} for the given {@link MappingMongoConverter}. + * + * @param converter must not be {@literal null}. + */ + public PersistentEntitiesFactoryBean(MappingMongoConverter converter) { + this.converter = converter; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ + @Override + public PersistentEntities getObject() throws Exception { + return PersistentEntities.of(converter.getMappingContext()); + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + @Override + public Class getObjectType() { + return PersistentEntities.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#isSingleton() + */ + @Override + public boolean isSingleton() { + return true; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java new file mode 100644 index 0000000000..20f7d16602 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReactiveMongoAuditingRegistrar.java @@ -0,0 +1,97 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.config; + +import java.lang.annotation.Annotation; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler; +import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; +import org.springframework.data.auditing.config.AuditingConfiguration; +import org.springframework.data.config.ParsingUtils; +import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback; +import org.springframework.util.Assert; + +/** + * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableReactiveMongoAuditing} annotation. + * + * @author Mark Paluch + * @since 3.1 + */ +class ReactiveMongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableReactiveMongoAuditing.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditingHandlerBeanName() + */ + @Override + protected String getAuditingHandlerBeanName() { + return "reactiveMongoAuditingHandler"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditHandlerBeanDefinitionBuilder(org.springframework.data.auditing.config.AuditingConfiguration) + */ + @Override + protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingConfiguration configuration) { + + Assert.notNull(configuration, "AuditingConfiguration must not be null!"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveIsNewAwareAuditingHandler.class); + + BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class); + definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); + + builder.addConstructorArgValue(definition.getBeanDefinition()); + return configureDefaultAuditHandlerAttributes(configuration, builder); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerAuditListener(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry) + */ + @Override + protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition, + BeanDefinitionRegistry registry) { + + Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!"); + Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class); + + builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)); + builder.getRawBeanDefinition().setSource(auditingHandlerDefinition.getSource()); + + registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(), + registry); + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 015cbf25b0..f497e2aa98 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -333,7 +333,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws if (mappingContext instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher); } - + ReactiveMongoAuditingRegistrar resourceLoader = applicationContext; projectionFactory.setBeanFactory(applicationContext); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java index 368257067d..4c1e9146fa 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAuditingEntityCallback.java @@ -15,13 +15,12 @@ */ package org.springframework.data.mongodb.core.mapping.event; -import reactor.core.publisher.Mono; - import org.reactivestreams.Publisher; + import org.springframework.beans.factory.ObjectFactory; import org.springframework.core.Ordered; import org.springframework.data.auditing.AuditingHandler; -import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler; import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.context.MappingContext; import org.springframework.util.Assert; @@ -34,7 +33,7 @@ */ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCallback, Ordered { - private final ObjectFactory auditingHandlerFactory; + private final ObjectFactory auditingHandlerFactory; /** * Creates a new {@link ReactiveAuditingEntityCallback} using the given {@link MappingContext} and @@ -42,19 +41,19 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall * * @param auditingHandlerFactory must not be {@literal null}. */ - public ReactiveAuditingEntityCallback(ObjectFactory auditingHandlerFactory) { + public ReactiveAuditingEntityCallback(ObjectFactory auditingHandlerFactory) { Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!"); this.auditingHandlerFactory = auditingHandlerFactory; } - /* + /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback#onBeforeConvert(java.lang.Object, java.lang.String) */ @Override public Publisher onBeforeConvert(Object entity, String collection) { - return Mono.just(auditingHandlerFactory.getObject().markAudited(entity)); + return auditingHandlerFactory.getObject().markAudited(entity); } /* diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index f79b88e456..7f2ce737e7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.config; import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -30,13 +29,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; -import org.springframework.data.domain.AuditorAware; +import org.springframework.data.domain.ReactiveAuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -57,17 +57,16 @@ */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) @ContextConfiguration -public class ReactiveAuditingTests { +class ReactiveAuditingTests { static @Client MongoClient mongoClient; @Autowired ReactiveAuditablePersonRepository auditablePersonRepository; - @Autowired AuditorAware auditorAware; @Autowired MongoMappingContext context; @Autowired ReactiveMongoOperations operations; @Configuration - @EnableMongoAuditing(auditorAwareRef = "auditorProvider") + @EnableReactiveMongoAuditing @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true, includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ReactiveAuditablePersonRepository.class)) static class Config extends AbstractReactiveMongoConfiguration { @@ -89,14 +88,17 @@ protected Set> getInitialEntitySet() { } @Bean - @SuppressWarnings("unchecked") - public AuditorAware auditorProvider() { - return mock(AuditorAware.class); + public ReactiveAuditorAware auditorProvider() { + + AuditablePerson person = new AuditablePerson("some-person"); + person.setId("foo"); + + return () -> Mono.just(person); } } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithWrapperVersion() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -106,7 +108,7 @@ public void auditingWorksForVersionedEntityWithWrapperVersion() { } @Test // DATAMONGO-2179 - public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { + void auditingWorksForVersionedEntityBatchWithWrapperVersion() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -115,8 +117,8 @@ public void auditingWorksForVersionedEntityBatchWithWrapperVersion() { null, 0L, 1L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithSimpleVersion() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithSimpleVersion() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // @@ -125,8 +127,8 @@ public void auditingWorksForVersionedEntityWithSimpleVersion() { 0L, 1L, 2L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), // it -> it.version, // @@ -135,8 +137,8 @@ public void auditingWorksForVersionedEntityWithWrapperVersionOnTemplate() { null, 0L, 1L); } - @Test // DATAMONGO-2139, DATAMONGO-2150 - public void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { + @Test // DATAMONGO-2139, DATAMONGO-2150, DATAMONGO-2586 + void auditingWorksForVersionedEntityWithSimpleVersionOnTemplate() { verifyAuditingViaVersionProperty(new SimpleVersionedAuditablePerson(), // it -> it.version, // AuditablePerson::getCreatedAt, // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 46b575f35f..78b1f05f2f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.*; +import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import reactor.util.function.Tuples; @@ -29,14 +30,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.Version; +import org.springframework.data.domain.ReactiveAuditorAware; import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; -import org.springframework.data.mongodb.config.EnableMongoAuditing; +import org.springframework.data.mongodb.config.EnableReactiveMongoAuditing; import org.springframework.data.mongodb.core.KAuditableVersionedEntity; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.mapping.Document; @@ -50,17 +54,20 @@ import com.mongodb.reactivestreams.client.MongoClient; /** + * Integration tests for {@link EnableReactiveMongoAuditing} through {@link ReactiveMongoTemplate}. + * * @author Christoph Strobl + * @author Mark Paluch */ @ExtendWith({ MongoClientExtension.class, SpringExtension.class }) -public class ReactiveMongoTemplateAuditingTests { +class ReactiveMongoTemplateAuditingTests { static final String DB_NAME = "mongo-template-audit-tests"; static @Client MongoClient mongoClient; @Configuration - @EnableMongoAuditing + @EnableReactiveMongoAuditing static class Conf extends AbstractReactiveMongoConfiguration { @Bean @@ -84,7 +91,7 @@ protected Set> getInitialEntitySet() { @Autowired MongoClient client; @BeforeEach - public void setUp() { + void setUp() { MongoTestUtils.flushCollection(DB_NAME, template.getCollectionName(ImmutableAuditableEntityWithVersion.class), client); @@ -92,7 +99,7 @@ public void setUp() { } @Test // DATAMONGO-2346 - public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() { + void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() { ImmutableAuditableEntityWithVersion entity = new ImmutableAuditableEntityWithVersion(null, "value", null, null); @@ -114,7 +121,7 @@ public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSa } @Test // DATAMONGO-2346 - public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() { + void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() { KAuditableVersionedEntity entity = new KAuditableVersionedEntity(null, "value", null, null); diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 1a1fc849d9..d0c9317f81 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,11 @@ [[new-features]] = New & Noteworthy +[[new-features.3.1]] +== What's New in Spring Data MongoDB 3.1 + +* <> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`. + [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 diff --git a/src/main/asciidoc/reference/mongo-auditing.adoc b/src/main/asciidoc/reference/mongo-auditing.adoc index eabc532c0c..b7abbe7112 100644 --- a/src/main/asciidoc/reference/mongo-auditing.adoc +++ b/src/main/asciidoc/reference/mongo-auditing.adoc @@ -30,3 +30,22 @@ 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` + +.Activating auditing using JavaConfig +==== +[source,java] +---- +@Configuration +@EnableReactiveMongoAuditing +class Config { + + @Bean + public ReactiveAuditorAware myAuditorProvider() { + return new AuditorAwareImpl(); + } +} +---- +==== +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`. +