Skip to content

Commit f97c703

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 0a3e5d0 commit f97c703

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
@@ -1001,23 +1001,23 @@ private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity
10011001
doInsert(collectionName, objectToSave, this.mongoConverter);
10021002
} else {
10031003

1004-
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
1005-
assertUpdateableIdIfNotSet(objectToSave);
1006-
1007-
// Create query for entity with the id and old version
1008-
Object id = convertingAccessor.getProperty(idProperty);
1009-
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
1010-
10111004
// Bump version number
10121005
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
10131006

1007+
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
1008+
assertUpdateableIdIfNotSet(objectToSave);
1009+
10141010
BasicDBObject dbObject = new BasicDBObject();
10151011

10161012
this.mongoConverter.write(objectToSave, dbObject);
10171013

10181014
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName));
10191015
Update update = Update.fromDBObject(dbObject, ID_FIELD);
10201016

1017+
// Create query for entity with the id and old version
1018+
Object id = convertingAccessor.getProperty(idProperty);
1019+
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
1020+
10211021
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
10221022
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName));
10231023
}

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}.
@@ -465,6 +468,33 @@ public void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferent
465468
assertThat(captor.getValue().getLimit(), is(1000));
466469
}
467470

471+
@Test // DATAMONGO-1639
472+
public void beforeConvertEventForUpdateSeesNextVersion() {
473+
474+
final VersionedEntity entity = new VersionedEntity();
475+
entity.id = 1;
476+
entity.version = 0;
477+
478+
GenericApplicationContext context = new GenericApplicationContext();
479+
context.refresh();
480+
context.addApplicationListener(new AbstractMongoEventListener<VersionedEntity>() {
481+
482+
@Override
483+
public void onBeforeConvert(BeforeConvertEvent<VersionedEntity> event) {
484+
assertThat(event.getSource().version, is(1));
485+
}
486+
});
487+
488+
template.setApplicationContext(context);
489+
490+
MongoTemplate spy = Mockito.spy(template);
491+
492+
doReturn(mock(WriteResult.class)).when(spy).doUpdate(anyString(), Mockito.any(Query.class),
493+
Mockito.any(Update.class), Mockito.any(Class.class), anyBoolean(), anyBoolean());
494+
495+
spy.save(entity);
496+
}
497+
468498
class AutogenerateableId {
469499

470500
@Id BigInteger id;

0 commit comments

Comments
 (0)