diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraAuditingRegistrar.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraAuditingRegistrar.java index cd818fd61..00ecd700f 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraAuditingRegistrar.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/CassandraAuditingRegistrar.java @@ -17,7 +17,6 @@ package org.springframework.data.cassandra.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; @@ -27,15 +26,9 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.auditing.IsNewAwareAuditingHandler; import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; import org.springframework.data.auditing.config.AuditingConfiguration; -import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; -import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity; -import org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty; import org.springframework.data.cassandra.core.mapping.event.AuditingEntityCallback; -import org.springframework.data.cassandra.core.mapping.event.ReactiveAuditingEntityCallback; import org.springframework.data.config.ParsingUtils; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; /** * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableCassandraAuditing} annotation. @@ -45,9 +38,6 @@ import org.springframework.util.ClassUtils; */ class CassandraAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { - private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono", - CassandraAuditingRegistrar.class.getClassLoader()); - /* * (non-Javadoc) * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() @@ -90,7 +80,7 @@ class CassandraAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class); - BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(CassandraMappingContextLookup.class); + BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(PersistentEntitiesFactoryBean.class); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); builder.addConstructorArgValue(definition.getBeanDefinition()); @@ -116,67 +106,6 @@ class CassandraAuditingRegistrar 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 org.springframework.data.cassandra.core.convert.MappingCassandraConverter} bean available in the application - * context. - */ - static class CassandraMappingContextLookup - implements FactoryBean, CassandraPersistentProperty>> { - - private final MappingCassandraConverter converter; - - /** - * Creates a new {@link CassandraMappingContextLookup} for the given {@link MappingCassandraConverter}. - * - * @param converter must not be {@literal null}. - */ - public CassandraMappingContextLookup(MappingCassandraConverter converter) { - this.converter = converter; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObject() - */ - @Override - public MappingContext, CassandraPersistentProperty> 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-cassandra/src/main/java/org/springframework/data/cassandra/config/EnableReactiveCassandraAuditing.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/EnableReactiveCassandraAuditing.java new file mode 100644 index 000000000..98d2b7d18 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/EnableReactiveCassandraAuditing.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.cassandra.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 Cassandra using reactive infrastructure via annotation configuration. + * + * @author Mark Paluch + * @since 3.1 + */ +@Inherited +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(ReactiveCassandraAuditingRegistrar.class) +public @interface EnableReactiveCassandraAuditing { + + /** + * Configures the {@link ReactiveAuditorAware} bean to be used to lookup the current principal. + * + * @return + */ + String auditorAwareRef() default ""; + + /** + * Configures whether the creation and modification dates are set. Defaults to {@literal true}. + * + * @return + */ + boolean setDates() default true; + + /** + * Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}. + * + * @return + */ + boolean modifyOnCreate() default true; + + /** + * Configures a {@link DateTimeProvider} bean name that allows customizing the + * {@link java.time.temporal.TemporalAccessor} to be used for setting creation and modification dates. + * + * @return + */ + String dateTimeProviderRef() default ""; +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/PersistentEntitiesFactoryBean.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/PersistentEntitiesFactoryBean.java new file mode 100644 index 000000000..06dcdcb5e --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/PersistentEntitiesFactoryBean.java @@ -0,0 +1,57 @@ +/* + * 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.cassandra.config; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.context.PersistentEntities; + +/** + * Simple helper to be able to wire the {@link MappingContext} from a {@link MappingCassandraConverter} bean available + * in the application context. + */ +class PersistentEntitiesFactoryBean implements FactoryBean { + + private final MappingCassandraConverter converter; + + /** + * Creates a new {@link PersistentEntitiesFactoryBean} for the given {@link MappingCassandraConverter}. + * + * @param converter must not be {@literal null}. + */ + public PersistentEntitiesFactoryBean(MappingCassandraConverter converter) { + this.converter = converter; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ + @Override + public PersistentEntities getObject() { + return PersistentEntities.of(converter.getMappingContext()); + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + @Override + public Class getObjectType() { + return PersistentEntities.class; + } +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/ReactiveCassandraAuditingRegistrar.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/ReactiveCassandraAuditingRegistrar.java new file mode 100644 index 000000000..b07ac8f40 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/ReactiveCassandraAuditingRegistrar.java @@ -0,0 +1,110 @@ +/* + * 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.cassandra.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.cassandra.core.mapping.event.ReactiveAuditingEntityCallback; +import org.springframework.data.config.ParsingUtils; +import org.springframework.util.Assert; + +/** + * {@link ImportBeanDefinitionRegistrar} to enable {@link EnableReactiveCassandraAuditing} annotation. + * + * @author Mark Paluch + * @since 3.1 + */ +class ReactiveCassandraAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport { + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableReactiveCassandraAuditing.class; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAuditingHandlerBeanName() + */ + @Override + protected String getAuditingHandlerBeanName() { + return "cassandraAuditingHandler"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) + */ + @Override + public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { + + Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!"); + Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); + + super.registerBeanDefinitions(annotationMetadata, registry); + } + + /* + * (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-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallback.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallback.java index d92799b78..2488c22de 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallback.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallback.java @@ -19,8 +19,7 @@ import reactor.core.publisher.Mono; 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; @@ -35,15 +34,15 @@ import com.datastax.oss.driver.api.core.CqlIdentifier; */ 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 - * {@link AuditingHandler} provided by the given {@link ObjectFactory}. + * {@link ReactiveIsNewAwareAuditingHandler} provided by the given {@link ObjectFactory}. * * @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; @@ -55,7 +54,7 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall */ @Override public Mono onBeforeConvert(Object entity, CqlIdentifier tableName) { - return Mono.just(auditingHandlerFactory.getObject().markAudited(entity)); + return auditingHandlerFactory.getObject().markAudited(entity); } /* diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/config/ReactiveAuditingTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/config/ReactiveAuditingTests.java new file mode 100644 index 000000000..e40db522e --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/config/ReactiveAuditingTests.java @@ -0,0 +1,109 @@ +/* + * 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.cassandra.config; + +import static org.assertj.core.api.Assertions.*; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.time.LocalDateTime; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.cassandra.core.convert.CassandraConverter; +import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; +import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; +import org.springframework.data.cassandra.core.mapping.Table; +import org.springframework.data.cassandra.core.mapping.event.ReactiveBeforeConvertCallback; +import org.springframework.data.domain.ReactiveAuditorAware; +import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import com.datastax.oss.driver.api.core.CqlIdentifier; + +/** + * Abstract integration tests for the reactive auditing support. + * + * @author Mark Paluch + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +public class ReactiveAuditingTests { + + @Autowired ApplicationContext context; + + @EnableReactiveCassandraAuditing + @Configuration + static class TestConfig { + + @Bean + public CassandraMappingContext mappingContext() { + return new CassandraMappingContext(); + } + + @Bean + public CassandraConverter cassandraConverter(CassandraMappingContext mappingContext) { + return new MappingCassandraConverter(mappingContext); + } + + @Bean + public ReactiveAuditorAware auditorAware() { + return () -> Mono.just("Walter"); + } + } + + @Test // DATACASS-784 + public void enablesAuditingAndSetsPropertiesAccordingly() { + + CassandraMappingContext mappingContext = context.getBean(CassandraMappingContext.class); + mappingContext.getPersistentEntity(Entity.class); + + ReactiveEntityCallbacks callbacks = ReactiveEntityCallbacks.create(context); + + Entity entity = new Entity(); + callbacks.callback(ReactiveBeforeConvertCallback.class, entity, CqlIdentifier.fromCql("entity")) + .as(StepVerifier::create).consumeNextWith(actual -> { + + assertThat(actual.created).isNotNull(); + assertThat(actual.createdBy).isEqualTo("Walter"); + }).verifyComplete(); + } + + @Table + class Entity { + + @Id Long id; + @CreatedDate LocalDateTime created; + @CreatedBy String createdBy; + LocalDateTime modified; + + @LastModifiedDate + public LocalDateTime getModified() { + return modified; + } + } +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallbackUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallbackUnitTests.java index accb31566..19ee3c6a0 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallbackUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/event/ReactiveAuditingEntityCallbackUnitTests.java @@ -22,11 +22,11 @@ import static org.mockito.Mockito.*; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.Value; -import lombok.experimental.Wither; import java.util.Collections; import java.util.Date; +import lombok.With; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,10 +38,12 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.mapping.context.PersistentEntities; import com.datastax.oss.driver.api.core.CqlIdentifier; +import reactor.core.publisher.Mono; /** * Unit tests for {@link ReactiveAuditingEntityCallback}. @@ -51,7 +53,7 @@ import com.datastax.oss.driver.api.core.CqlIdentifier; @RunWith(MockitoJUnitRunner.class) public class ReactiveAuditingEntityCallbackUnitTests { - IsNewAwareAuditingHandler handler; + ReactiveIsNewAwareAuditingHandler handler; ReactiveAuditingEntityCallback callback; @Before @@ -60,10 +62,11 @@ public class ReactiveAuditingEntityCallbackUnitTests { CassandraMappingContext mappingContext = new CassandraMappingContext(); mappingContext.getPersistentEntity(Sample.class); - handler = spy(new IsNewAwareAuditingHandler(new PersistentEntities(Collections.singletonList(mappingContext)))); + handler = spy( + new ReactiveIsNewAwareAuditingHandler(new PersistentEntities(Collections.singletonList(mappingContext)))); - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markCreated(any()); - doAnswer(AdditionalAnswers.returnsArgAt(0)).when(handler).markModified(any()); + doAnswer(invocation -> Mono.just(invocation.getArgument(0))).when(handler).markCreated(any()); + doAnswer(invocation -> Mono.just(invocation.getArgument(0))).when(handler).markModified(any()); callback = new ReactiveAuditingEntityCallback(() -> handler); } @@ -101,14 +104,14 @@ public class ReactiveAuditingEntityCallbackUnitTests { assertThat(callback.getOrder()).isEqualTo(100); } - @Test // DATACASS-4 + @Test // DATACASS-4, DATACASS-784 public void propagatesChangedInstanceToEvent() { ImmutableSample sample = new ImmutableSample(); ImmutableSample newSample = new ImmutableSample(); - IsNewAwareAuditingHandler handler = mock(IsNewAwareAuditingHandler.class); - doReturn(newSample).when(handler).markAudited(eq(sample)); + ReactiveIsNewAwareAuditingHandler handler = mock(ReactiveIsNewAwareAuditingHandler.class); + doReturn(Mono.just(newSample)).when(handler).markAudited(eq(sample)); ReactiveAuditingEntityCallback listener = new ReactiveAuditingEntityCallback(() -> handler); Object result = listener.onBeforeConvert(sample, CqlIdentifier.fromCql("foo")).block(); @@ -124,7 +127,7 @@ public class ReactiveAuditingEntityCallbackUnitTests { } @Value - @Wither + @With @AllArgsConstructor @NoArgsConstructor(force = true) static class ImmutableSample { diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index efd325ca9..5352b7e3f 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -3,6 +3,11 @@ This chapter summarizes changes and new features for each release. +[[new-features.3-1-0]] +== What's new in Spring Data for Apache Cassandra 3.1 + +* <> enabled through `@EnableReactiveCassandraAuditing`. `@EnableCassandraAuditing` no longer registers `ReactiveAuditingEntityCallback`. + [[new-features.3-0-0]] == What's new in Spring Data for Apache Cassandra 3.0 diff --git a/src/main/asciidoc/reference/cassandra-auditing.adoc b/src/main/asciidoc/reference/cassandra-auditing.adoc index 44e7f57d7..ed48773de 100644 --- a/src/main/asciidoc/reference/cassandra-auditing.adoc +++ b/src/main/asciidoc/reference/cassandra-auditing.adoc @@ -31,3 +31,23 @@ class Config { If you expose a bean of type `AuditorAware` 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 `@EnableCassandraAuditing`. + +To enable auditing, leveraging a reactive programming model, use the `@EnableReactiveCassandraAuditing` 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 `@EnableReactiveCassandraAuditing`. + +.Activating reactive auditing using JavaConfig +==== +[source,java] +---- +@Configuration +@EnableReactiveCassandraAuditing +class Config { + + @Bean + public ReactiveAuditorAware myAuditorProvider() { + return new AuditorAwareImpl(); + } +} +---- +====