DATAMONGO-2586 - Add support for reactive auditing.

We now provide a fully reactive variant for auditing with EnableReactiveMongoAuditing.

Original Pull Request: #877
This commit is contained in:
Mark Paluch
2020-07-14 11:23:31 +02:00
committed by Christoph Strobl
parent 2c1a3cf03e
commit 6bafcea539
10 changed files with 300 additions and 105 deletions

View File

@@ -61,8 +61,8 @@ public @interface EnableMongoAuditing {
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.
*/

View File

@@ -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 "";
}

View File

@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.config;
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.IsNewAwareAuditingHandler;
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 @@ import org.springframework.util.ClassUtils;
*/
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 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
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 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
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<MappingContext<? extends MongoPersistentEntity<?>, 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<? extends MongoPersistentEntity<?>, 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;
}
}
}

View File

@@ -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<PersistentEntities> {
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;
}
}

View File

@@ -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<? extends Annotation> 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);
}
}

View File

@@ -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 @@ import org.springframework.util.Assert;
*/
public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCallback<Object>, Ordered {
private final ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory;
private final ObjectFactory<ReactiveIsNewAwareAuditingHandler> 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<IsNewAwareAuditingHandler> auditingHandlerFactory) {
public ReactiveAuditingEntityCallback(ObjectFactory<ReactiveIsNewAwareAuditingHandler> 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<Object> onBeforeConvert(Object entity, String collection) {
return Mono.just(auditingHandlerFactory.getObject().markAudited(entity));
return auditingHandlerFactory.getObject().markAudited(entity);
}
/*

View File

@@ -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 java.util.function.Function;
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 @@ import com.mongodb.reactivestreams.client.MongoClient;
*/
@ExtendWith({ MongoClientExtension.class, SpringExtension.class })
@ContextConfiguration
public class ReactiveAuditingTests {
class ReactiveAuditingTests {
static @Client MongoClient mongoClient;
@Autowired ReactiveAuditablePersonRepository auditablePersonRepository;
@Autowired AuditorAware<AuditablePerson> 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 @@ public class ReactiveAuditingTests {
}
@Bean
@SuppressWarnings("unchecked")
public AuditorAware<AuditablePerson> auditorProvider() {
return mock(AuditorAware.class);
public ReactiveAuditorAware<AuditablePerson> 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 class ReactiveAuditingTests {
}
@Test // DATAMONGO-2179
public void auditingWorksForVersionedEntityBatchWithWrapperVersion() {
void auditingWorksForVersionedEntityBatchWithWrapperVersion() {
verifyAuditingViaVersionProperty(new VersionedAuditablePerson(), //
it -> it.version, //
@@ -115,8 +117,8 @@ public class ReactiveAuditingTests {
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 class ReactiveAuditingTests {
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 class ReactiveAuditingTests {
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, //

View File

@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.auditing;
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 java.util.Set;
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 org.springframework.test.context.junit.jupiter.SpringExtension;
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 @@ public class ReactiveMongoTemplateAuditingTests {
@Autowired MongoClient client;
@BeforeEach
public void setUp() {
void setUp() {
MongoTestUtils.flushCollection(DB_NAME, template.getCollectionName(ImmutableAuditableEntityWithVersion.class),
client);
@@ -92,7 +99,7 @@ public class ReactiveMongoTemplateAuditingTests {
}
@Test // DATAMONGO-2346
public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() {
void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedEntityOnSave() {
ImmutableAuditableEntityWithVersion entity = new ImmutableAuditableEntityWithVersion(null, "value", null, null);
@@ -114,7 +121,7 @@ public class ReactiveMongoTemplateAuditingTests {
}
@Test // DATAMONGO-2346
public void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() {
void auditingSetsLastModifiedDateCorrectlyForImmutableVersionedKotlinEntityOnSave() {
KAuditableVersionedEntity entity = new KAuditableVersionedEntity(null, "value", null, null);

View File

@@ -1,6 +1,11 @@
[[new-features]]
= New & Noteworthy
[[new-features.3.1]]
== What's New in Spring Data MongoDB 3.1
* <<mongo.auditing,Reactive auditing>> enabled through `@EnableReactiveMongoAuditing`. `@EnableMongoAuditing` no longer registers `ReactiveAuditingEntityCallback`.
[[new-features.3.0]]
== What's New in Spring Data MongoDB 3.0

View File

@@ -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<AuditableUser> 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`.