DATAMONGO-2189 - Fix AfterSaveEvent to contain the saved entity in ReactiveMongoTemplate.insert(…).

ReactiveMongoTemplate.insert(…) now uses the saved entity when emitting AfterSaveEvent. This change affects usage of immutable objects that are using Id generation. Previously, the to-be-saved entity instance was used which left the Id unpopulated.

Original Pull Request: #638
This commit is contained in:
Mark Paluch
2019-01-24 14:11:41 +01:00
committed by Christoph Strobl
parent 85aa3927a6
commit bdfe4e99ed
3 changed files with 92 additions and 1 deletions

View File

@@ -1252,7 +1252,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Mono<T> afterInsert = insertDocument(collectionName, dbDoc, initialized.getClass()).map(id -> {
T saved = entity.populateIdIfNecessary(id);
maybeEmitEvent(new AfterSaveEvent<>(initialized, dbDoc, collectionName));
maybeEmitEvent(new AfterSaveEvent<>(saved, dbDoc, collectionName));
return saved;
});

View File

@@ -41,6 +41,7 @@ import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -85,8 +86,10 @@ import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoId;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
@@ -3511,6 +3514,44 @@ public class MongoTemplateTests {
assertThat(document.id, is(notNullValue()));
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsertAll() {
AtomicReference<ImmutableVersioned> saved = createAfterSaveReference();
template.insertAll(Collections.singletonList(new ImmutableVersioned()));
assertThat(saved.get(), is(notNullValue()));
assertThat(saved.get().id, is(notNullValue()));
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsert() {
AtomicReference<ImmutableVersioned> saved = createAfterSaveReference();
template.insert(new ImmutableVersioned());
assertThat(saved.get(), is(notNullValue()));
assertThat(saved.get().id, is(notNullValue()));
}
private AtomicReference<ImmutableVersioned> createAfterSaveReference() {
AtomicReference<ImmutableVersioned> saved = new AtomicReference<>();
context.addApplicationListener(new AbstractMongoEventListener<ImmutableVersioned>() {
@Override
public void onAfterSave(AfterSaveEvent<ImmutableVersioned> event) {
saved.set(event.getSource());
}
});
return saved;
}
@Test // DATAMONGO-1509
public void findsByGenericNestedListElements() {

View File

@@ -39,6 +39,7 @@ import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -54,6 +55,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -71,11 +73,14 @@ import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexOperationsAdapter;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.test.util.ReplicaSet;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -95,6 +100,7 @@ public class ReactiveMongoTemplateTests {
@Autowired SimpleReactiveMongoDatabaseFactory factory;
@Autowired ReactiveMongoTemplate template;
@Autowired ConfigurableApplicationContext context;
@Before
public void setUp() {
@@ -1318,6 +1324,50 @@ public class ReactiveMongoTemplateTests {
.verifyComplete();
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsert() {
AtomicReference<ImmutableVersioned> saved = createAfterSaveReference();
template.insert(new ImmutableVersioned()) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
assertThat(saved.get()).isNotNull();
assertThat(saved.get().id).isNotNull();
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsertAll() {
AtomicReference<ImmutableVersioned> saved = createAfterSaveReference();
template.insertAll(Collections.singleton(new ImmutableVersioned())) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
assertThat(saved.get()).isNotNull();
assertThat(saved.get().id).isNotNull();
}
private AtomicReference<ImmutableVersioned> createAfterSaveReference() {
AtomicReference<ImmutableVersioned> saved = new AtomicReference<>();
context.addApplicationListener(new AbstractMongoEventListener<ImmutableVersioned>() {
@Override
public void onAfterSave(AfterSaveEvent<ImmutableVersioned> event) {
saved.set(event.getSource());
}
});
return saved;
}
@Test // DATAMONGO-2012
public void watchesDatabaseCorrectly() throws InterruptedException {