Skip to content

Commit b46baa8

Browse files
committed
DATAMONGO-1639 - Make sure BeforeConvertEvent sees new version for updates.
The changes for DATAMONGO-1617 subtley changed the behavior for entity updates in terms of the version value they see for entities using optimistic locking. Previously the updates already saw the new version value, where after the fix for DATAMONGO-1617 it saw the old one. That caused BeforeConvertEvent listeners not being able to distinguish between an original insert and the first update anymore. This change is now rolled back and we introduced a test case that encodes this expectation explicitly.
1 parent 96d45ca commit b46baa8

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -985,23 +985,23 @@ private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity
985985
doInsert(collectionName, objectToSave, this.mongoConverter);
986986
} else {
987987

988-
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
989-
assertUpdateableIdIfNotSet(objectToSave);
990-
991-
// Create query for entity with the id and old version
992-
Object id = convertingAccessor.getProperty(idProperty);
993-
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
994-
995988
// Bump version number
996989
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
997990

991+
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
992+
assertUpdateableIdIfNotSet(objectToSave);
993+
998994
BasicDBObject dbObject = new BasicDBObject();
999995

1000996
this.mongoConverter.write(objectToSave, dbObject);
1001997

1002998
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName));
1003999
Update update = Update.fromDBObject(dbObject, ID_FIELD);
10041000

1001+
// Create query for entity with the id and old version
1002+
Object id = convertingAccessor.getProperty(idProperty);
1003+
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
1004+
10051005
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
10061006
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName));
10071007
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
import org.springframework.data.mongodb.core.convert.QueryMapper;
5353
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
5454
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
55+
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
56+
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
5557
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
5658
import org.springframework.data.mongodb.core.query.BasicQuery;
5759
import org.springframework.data.mongodb.core.query.Criteria;
@@ -72,6 +74,7 @@
7274
import com.mongodb.Mongo;
7375
import com.mongodb.MongoException;
7476
import com.mongodb.ReadPreference;
77+
import com.mongodb.WriteResult;
7578

7679
/**
7780
* Unit tests for {@link MongoTemplate}.
@@ -531,6 +534,33 @@ public void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferent
531534
assertThat(captor.getValue().getLimit(), is(1000));
532535
}
533536

537+
@Test // DATAMONGO-1639
538+
public void beforeConvertEventForUpdateSeesNextVersion() {
539+
540+
final VersionedEntity entity = new VersionedEntity();
541+
entity.id = 1;
542+
entity.version = 0;
543+
544+
GenericApplicationContext context = new GenericApplicationContext();
545+
context.refresh();
546+
context.addApplicationListener(new AbstractMongoEventListener<VersionedEntity>() {
547+
548+
@Override
549+
public void onBeforeConvert(BeforeConvertEvent<VersionedEntity> event) {
550+
assertThat(event.getSource().version, is(1));
551+
}
552+
});
553+
554+
template.setApplicationContext(context);
555+
556+
MongoTemplate spy = Mockito.spy(template);
557+
558+
doReturn(mock(WriteResult.class)).when(spy).doUpdate(anyString(), Mockito.any(Query.class),
559+
Mockito.any(Update.class), Mockito.any(Class.class), anyBoolean(), anyBoolean());
560+
561+
spy.save(entity);
562+
}
563+
534564
class AutogenerateableId {
535565

536566
@Id BigInteger id;

0 commit comments

Comments
 (0)