Browse Source

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
pull/640/head
Mark Paluch 7 years ago committed by Christoph Strobl
parent
commit
bdfe4e99ed
  1. 2
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
  2. 41
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
  3. 50
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java

2
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

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

41
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

@ -41,6 +41,7 @@ import java.math.BigInteger;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; 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.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.mapping.Field; 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.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; 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.AuditingEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
@ -3511,6 +3514,44 @@ public class MongoTemplateTests {
assertThat(document.id, is(notNullValue())); 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 @Test // DATAMONGO-1509
public void findsByGenericNestedListElements() { public void findsByGenericNestedListElements() {

50
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java

@ -39,6 +39,7 @@ import java.util.Map;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -54,6 +55,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessApiUsageException; 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.GeospatialIndex;
import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexOperationsAdapter; 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.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.test.util.ReplicaSet; 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.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -95,6 +100,7 @@ public class ReactiveMongoTemplateTests {
@Autowired SimpleReactiveMongoDatabaseFactory factory; @Autowired SimpleReactiveMongoDatabaseFactory factory;
@Autowired ReactiveMongoTemplate template; @Autowired ReactiveMongoTemplate template;
@Autowired ConfigurableApplicationContext context;
@Before @Before
public void setUp() { public void setUp() {
@ -1318,6 +1324,50 @@ public class ReactiveMongoTemplateTests {
.verifyComplete(); .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 @Test // DATAMONGO-2012
public void watchesDatabaseCorrectly() throws InterruptedException { public void watchesDatabaseCorrectly() throws InterruptedException {

Loading…
Cancel
Save