diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 1f3fd76fe..6cd158820 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -1001,16 +1001,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { doInsert(collectionName, objectToSave, this.mongoConverter); } else { - maybeEmitEvent(new BeforeConvertEvent(objectToSave, collectionName)); - assertUpdateableIdIfNotSet(objectToSave); - - // Create query for entity with the id and old version - Object id = convertingAccessor.getProperty(idProperty); - Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version)); - // Bump version number convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1); + maybeEmitEvent(new BeforeConvertEvent(objectToSave, collectionName)); + assertUpdateableIdIfNotSet(objectToSave); + BasicDBObject dbObject = new BasicDBObject(); this.mongoConverter.write(objectToSave, dbObject); @@ -1018,6 +1014,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { maybeEmitEvent(new BeforeSaveEvent(objectToSave, dbObject, collectionName)); Update update = Update.fromDBObject(dbObject, ID_FIELD); + // Create query for entity with the id and old version + Object id = convertingAccessor.getProperty(idProperty); + Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version)); + doUpdate(collectionName, query, update, objectToSave.getClass(), false, false); maybeEmitEvent(new AfterSaveEvent(objectToSave, dbObject, collectionName)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index a4bc0595c..dcb8b9702 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -52,6 +52,8 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator; 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.BeforeConvertEvent; import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; @@ -72,6 +74,7 @@ import com.mongodb.MapReduceOutput; import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.ReadPreference; +import com.mongodb.WriteResult; /** * Unit tests for {@link MongoTemplate}. @@ -465,6 +468,33 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { assertThat(captor.getValue().getLimit(), is(1000)); } + @Test // DATAMONGO-1639 + public void beforeConvertEventForUpdateSeesNextVersion() { + + final VersionedEntity entity = new VersionedEntity(); + entity.id = 1; + entity.version = 0; + + GenericApplicationContext context = new GenericApplicationContext(); + context.refresh(); + context.addApplicationListener(new AbstractMongoEventListener() { + + @Override + public void onBeforeConvert(BeforeConvertEvent event) { + assertThat(event.getSource().version, is(1)); + } + }); + + template.setApplicationContext(context); + + MongoTemplate spy = Mockito.spy(template); + + doReturn(mock(WriteResult.class)).when(spy).doUpdate(anyString(), Mockito.any(Query.class), + Mockito.any(Update.class), Mockito.any(Class.class), anyBoolean(), anyBoolean()); + + spy.save(entity); + } + class AutogenerateableId { @Id BigInteger id;