Skip to content

Add configuration to disable entity lifecycle events #1291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-GH-1286-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data for Apache Cassandra</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-GH-1286-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-GH-1286-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

Expand Down Expand Up @@ -124,7 +125,7 @@ public class AsyncCassandraTemplate

private final StatementFactory statementFactory;

private @Nullable ApplicationEventPublisher eventPublisher;
private final EntityLifecycleEventDelegate eventDelegate;

private @Nullable EntityCallbacks entityCallbacks;

Expand Down Expand Up @@ -190,11 +191,12 @@ public AsyncCassandraTemplate(AsyncCqlTemplate asyncCqlTemplate, CassandraConver
this.entityOperations = new EntityOperations(converter);
this.exceptionTranslator = asyncCqlTemplate.getExceptionTranslator();
this.statementFactory = new StatementFactory(converter);
this.eventDelegate = new EntityLifecycleEventDelegate();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking: I'd prefer to initialize this on declaration since it does not depend on anything in the constructor.

}

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
this.eventDelegate.setPublisher(applicationEventPublisher);
}

@Override
Expand All @@ -214,6 +216,18 @@ public void setEntityCallbacks(@Nullable EntityCallbacks entityCallbacks) {
this.entityCallbacks = entityCallbacks;
}

/**
* Configure whether lifecycle events such as {@link AfterLoadEvent}, {@link BeforeSaveEvent}, etc. should be
* published or whether emission should be suppressed. Enabled by default.
*
* @param enabled {@code true} to enable entity lifecycle events; {@code false} to disable entity lifecycle events.
* @since 4.0
* @see CassandraMappingEvent
*/
public void setEntityLifecycleEventsEnabled(boolean enabled) {
this.eventDelegate.setEventsEnabled(enabled);
}

@Override
public AsyncCqlOperations getAsyncCqlOperations() {
return this.cqlOperations;
Expand Down Expand Up @@ -456,11 +470,12 @@ private ListenableFuture<Boolean> doDelete(Query query, Class<?> entityClass, Cq
tableName);
SimpleStatement delete = builder.build();

maybeEmitEvent(new BeforeDeleteEvent<>(delete, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(delete, entityClass, tableName));

ListenableFuture<Boolean> future = doExecute(delete, AsyncResultSet::wasApplied);

future.addCallback(success -> maybeEmitEvent(new AfterDeleteEvent<>(delete, entityClass, tableName)), e -> {});
future.addCallback(success -> maybeEmitEvent(() -> new AfterDeleteEvent<>(delete, entityClass, tableName)),
e -> {});

return future;
}
Expand Down Expand Up @@ -677,8 +692,8 @@ private ListenableFuture<WriteResult> doDeleteVersioned(Object entity, QueryOpti

if (!result.wasApplied()) {
throw new OptimisticLockingFailureException(
String.format("Cannot delete entity %s with version %s in table %s; Has it been modified meanwhile",
entity, source.getVersion(), tableName));
String.format("Cannot delete entity %s with version %s in table %s; Has it been modified meanwhile", entity,
source.getVersion(), tableName));
}
});
}
Expand All @@ -702,10 +717,11 @@ public ListenableFuture<Boolean> deleteById(Object id, Class<?> entityClass) {
StatementBuilder<Delete> builder = getStatementFactory().deleteById(id, entity, tableName);
SimpleStatement delete = builder.build();

maybeEmitEvent(new BeforeDeleteEvent<>(delete, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(delete, entityClass, tableName));

ListenableFuture<Boolean> future = doExecute(delete, AsyncResultSet::wasApplied);
future.addCallback(success -> maybeEmitEvent(new AfterDeleteEvent<>(delete, entityClass, tableName)), e -> {});
future.addCallback(success -> maybeEmitEvent(() -> new AfterDeleteEvent<>(delete, entityClass, tableName)),
e -> {});

return future;
}
Expand All @@ -719,10 +735,11 @@ public ListenableFuture<Void> truncate(Class<?> entityClass) {
Truncate truncate = QueryBuilder.truncate(tableName);
SimpleStatement statement = truncate.build();

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entityClass, tableName));

ListenableFuture<Boolean> future = doExecute(statement, AsyncResultSet::wasApplied);
future.addCallback(success -> maybeEmitEvent(new AfterDeleteEvent<>(statement, entityClass, tableName)), e -> {});
future.addCallback(success -> maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entityClass, tableName)),
e -> {});

return new MappingListenableFutureAdapter<>(future, aBoolean -> null);
}
Expand Down Expand Up @@ -753,7 +770,7 @@ private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIden
private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIdentifier tableName,
SimpleStatement statement, Consumer<WriteResult> beforeAfterSaveEvent) {

maybeEmitEvent(new BeforeSaveEvent<>(entity, tableName, statement));
maybeEmitEvent(() -> new BeforeSaveEvent<>(entity, tableName, statement));
T entityToSave = maybeCallBeforeSave(entity, tableName, statement);

ListenableFuture<AsyncResultSet> result = doQueryForResultSet(statement);
Expand All @@ -766,7 +783,7 @@ private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIden

beforeAfterSaveEvent.accept(writeResult);

maybeEmitEvent(new AfterSaveEvent<>(entityToSave, tableName));
maybeEmitEvent(() -> new AfterSaveEvent<>(entityToSave, tableName));

return writeResult;
});
Expand All @@ -775,7 +792,7 @@ private <T> ListenableFuture<EntityWriteResult<T>> executeSave(T entity, CqlIden
private ListenableFuture<WriteResult> executeDelete(Object entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));

ListenableFuture<AsyncResultSet> result = doQueryForResultSet(statement);

Expand All @@ -786,7 +803,7 @@ private ListenableFuture<WriteResult> executeDelete(Object entity, CqlIdentifier

resultConsumer.accept(writeResult);

maybeEmitEvent(new AfterDeleteEvent<>(statement, entity.getClass(), tableName));
maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entity.getClass(), tableName));

return writeResult;
});
Expand Down Expand Up @@ -864,9 +881,7 @@ public String getCql() {
}
}

return getAsyncCqlOperations()
.execute(new GetConfiguredPageSize())
.completable().join();
return getAsyncCqlOperations().execute(new GetConfiguredPageSize()).completable().join();
}

@SuppressWarnings("unchecked")
Expand All @@ -876,12 +891,12 @@ private <T> Function<Row, T> getMapper(Class<?> entityType, Class<T> targetType,

return row -> {

maybeEmitEvent(new AfterLoadEvent<>(row, targetType, tableName));
maybeEmitEvent(() -> new AfterLoadEvent<>(row, targetType, tableName));

T result = getConverter().project(projection, row);

if (result != null) {
maybeEmitEvent(new AfterConvertEvent<>(row, result, tableName));
maybeEmitEvent(() -> new AfterConvertEvent<>(row, result, tableName));
}

return result;
Expand All @@ -899,11 +914,8 @@ private static MappingCassandraConverter newConverter(CqlSession session) {
return converter;
}

protected <E extends CassandraMappingEvent<T>, T> void maybeEmitEvent(E event) {

if (this.eventPublisher != null) {
this.eventPublisher.publishEvent(event);
}
protected <E extends CassandraMappingEvent<T>, T> void maybeEmitEvent(Supplier<E> event) {
this.eventDelegate.publishEvent(event);
}

protected <T> T maybeCallBeforeConvert(T object, CqlIdentifier tableName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -118,7 +119,7 @@ public class CassandraTemplate implements CassandraOperations, ApplicationEventP

private final StatementFactory statementFactory;

private @Nullable ApplicationEventPublisher eventPublisher;
private final EntityLifecycleEventDelegate eventDelegate;

private @Nullable EntityCallbacks entityCallbacks;

Expand Down Expand Up @@ -183,6 +184,7 @@ public CassandraTemplate(CqlOperations cqlOperations, CassandraConverter convert
this.cqlOperations = cqlOperations;
this.entityOperations = new EntityOperations(converter);
this.statementFactory = new StatementFactory(new QueryMapper(converter), new UpdateMapper(converter));
this.eventDelegate = new EntityLifecycleEventDelegate();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again: I'd prefer initialization at declaration time when possible.

}

@Override
Expand All @@ -192,7 +194,7 @@ public CassandraBatchOperations batchOps(BatchType batchType) {

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
this.eventDelegate.setPublisher(applicationEventPublisher);
}

@Override
Expand All @@ -212,6 +214,18 @@ public void setEntityCallbacks(@Nullable EntityCallbacks entityCallbacks) {
this.entityCallbacks = entityCallbacks;
}

/**
* Configure whether lifecycle events such as {@link AfterLoadEvent}, {@link BeforeSaveEvent}, etc. should be
* published or whether emission should be suppressed. Enabled by default.
*
* @param enabled {@code true} to enable entity lifecycle events; {@code false} to disable entity lifecycle events.
* @since 4.0
* @see CassandraMappingEvent
*/
public void setEntityLifecycleEventsEnabled(boolean enabled) {
this.eventDelegate.setEventsEnabled(enabled);
}

@Override
public CqlOperations getCqlOperations() {
return this.cqlOperations;
Expand Down Expand Up @@ -488,11 +502,11 @@ WriteResult doDelete(Query query, Class<?> entityClass, CqlIdentifier tableName)
tableName);
SimpleStatement statement = delete.build();

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entityClass, tableName));

WriteResult writeResult = doExecute(statement);

maybeEmitEvent(new AfterDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entityClass, tableName));

return writeResult;
}
Expand Down Expand Up @@ -700,8 +714,8 @@ private WriteResult doDeleteVersioned(SimpleStatement statement, Object entity,

if (!result.wasApplied()) {
throw new OptimisticLockingFailureException(
String.format("Cannot delete entity %s with version %s in table %s; Has it been modified meanwhile",
entity, source.getVersion(), tableName));
String.format("Cannot delete entity %s with version %s in table %s; Has it been modified meanwhile", entity,
source.getVersion(), tableName));
}
});
}
Expand All @@ -722,11 +736,11 @@ public boolean deleteById(Object id, Class<?> entityClass) {
StatementBuilder<Delete> delete = getStatementFactory().deleteById(id, entity, tableName);
SimpleStatement statement = delete.build();

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entityClass, tableName));

boolean result = doExecute(statement).wasApplied();

maybeEmitEvent(new AfterDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entityClass, tableName));

return result;
}
Expand All @@ -740,11 +754,11 @@ public void truncate(Class<?> entityClass) {
Truncate truncate = QueryBuilder.truncate(tableName);
SimpleStatement statement = truncate.build();

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entityClass, tableName));

doExecute(statement);

maybeEmitEvent(new AfterDeleteEvent<>(statement, entityClass, tableName));
maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entityClass, tableName));
}

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -795,27 +809,27 @@ private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName,
private <T> EntityWriteResult<T> executeSave(T entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {

maybeEmitEvent(new BeforeSaveEvent<>(entity, tableName, statement));
maybeEmitEvent(() -> new BeforeSaveEvent<>(entity, tableName, statement));
T entityToSave = maybeCallBeforeSave(entity, tableName, statement);

WriteResult result = doExecute(statement);
resultConsumer.accept(result);

maybeEmitEvent(new AfterSaveEvent<>(entityToSave, tableName));
maybeEmitEvent(() -> new AfterSaveEvent<>(entityToSave, tableName));

return EntityWriteResult.of(result, entityToSave);
}

private WriteResult executeDelete(Object entity, CqlIdentifier tableName, SimpleStatement statement,
Consumer<WriteResult> resultConsumer) {

maybeEmitEvent(new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));
maybeEmitEvent(() -> new BeforeDeleteEvent<>(statement, entity.getClass(), tableName));

WriteResult result = doExecute(statement);

resultConsumer.accept(result);

maybeEmitEvent(new AfterDeleteEvent<>(statement, entity.getClass(), tableName));
maybeEmitEvent(() -> new AfterDeleteEvent<>(statement, entity.getClass(), tableName));

return result;
}
Expand Down Expand Up @@ -907,12 +921,12 @@ private <T> Function<Row, T> getMapper(EntityProjection<T, ?> projection, CqlIde

return row -> {

maybeEmitEvent(new AfterLoadEvent<>(row, targetType, tableName));
maybeEmitEvent(() -> new AfterLoadEvent<>(row, targetType, tableName));

T result = getConverter().project(projection, row);

if (result != null) {
maybeEmitEvent(new AfterConvertEvent<>(row, result, tableName));
maybeEmitEvent(() -> new AfterConvertEvent<>(row, result, tableName));
}

return result;
Expand All @@ -930,11 +944,8 @@ private static MappingCassandraConverter newConverter(CqlSession session) {
return converter;
}

protected <E extends CassandraMappingEvent<T>, T> void maybeEmitEvent(E event) {

if (this.eventPublisher != null) {
this.eventPublisher.publishEvent(event);
}
protected <E extends CassandraMappingEvent<T>, T> void maybeEmitEvent(Supplier<E> event) {
this.eventDelegate.publishEvent(event);
}

protected <T> T maybeCallBeforeConvert(T object, CqlIdentifier tableName) {
Expand Down
Loading