Skip to content

Commit 2f522ba

Browse files
committed
DATAMONGO-1513 - Fixed identifier population for event listener generated, non-ObjectId on batch inserts.
The methods in MongoTemplate inserting a batch of documents previously only returned database generated identifiers, more especially ObjectId ones. This caused non-ObjectId identifiers potentially generated by other parties — i.e. an event listener reacting to a BeforeSaveEvent — not being considered for source object identifier population. This commit adds a workaround augmenting the list of database generated identifiers with the ones actually present in the documents to be inserted. A follow-up ticket DATAMONGO-1519 was created to track the removal of the workaround in favor of a proper fix unfortunately requiring a change in public API (so a 2.0 candidate only). Related tickets: DATAMONGO-1519.
1 parent 2e6f919 commit 2f522ba

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,9 @@ protected <T> void doInsertBatch(String collectionName, Collection<? extends T>
932932
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc, collectionName));
933933
dbObjectList.add(dbDoc);
934934
}
935-
List<ObjectId> ids = insertDBObjectList(collectionName, dbObjectList);
935+
936+
List<Object> ids = consolidateIdentifiers(insertDBObjectList(collectionName, dbObjectList), dbObjectList);
937+
936938
int i = 0;
937939
for (T obj : batchToSave) {
938940
if (i < ids.size()) {
@@ -1037,6 +1039,8 @@ public Object doInCollection(DBCollection collection) throws MongoException, Dat
10371039
});
10381040
}
10391041

1042+
// TODO: 2.0 - Change method signature to return List<Object> and return all identifiers (DATAMONGO-1513,
1043+
// DATAMONGO-1519)
10401044
protected List<ObjectId> insertDBObjectList(final String collectionName, final List<DBObject> dbDocList) {
10411045
if (dbDocList.isEmpty()) {
10421046
return Collections.emptyList();
@@ -2115,6 +2119,28 @@ private static RuntimeException potentiallyConvertRuntimeException(RuntimeExcept
21152119
return resolved == null ? ex : resolved;
21162120
}
21172121

2122+
/**
2123+
* Returns all identifiers for the given documents. Will augment the given identifiers and fill in only the ones that
2124+
* are {@literal null} currently. This would've been better solved in {@link #insertDBObjectList(String, List)}
2125+
* directly but would require a signature change of that method.
2126+
*
2127+
* @param ids
2128+
* @param documents
2129+
* @return TODO: Remove for 2.0 and change method signature of {@link #insertDBObjectList(String, List)}.
2130+
*/
2131+
private static List<Object> consolidateIdentifiers(List<ObjectId> ids, List<DBObject> documents) {
2132+
2133+
List<Object> result = new ArrayList<Object>(ids.size());
2134+
2135+
for (int i = 0; i < ids.size(); i++) {
2136+
2137+
ObjectId objectId = ids.get(i);
2138+
result.add(objectId == null ? documents.get(i).get(ID_FIELD) : objectId);
2139+
}
2140+
2141+
return result;
2142+
}
2143+
21182144
// Callback implementations
21192145

21202146
/**

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.HashSet;
3434
import java.util.List;
3535
import java.util.Map;
36+
import java.util.UUID;
3637

3738
import org.bson.types.ObjectId;
3839
import org.joda.time.DateTime;
@@ -43,6 +44,7 @@
4344
import org.junit.rules.ExpectedException;
4445
import org.junit.runner.RunWith;
4546
import org.springframework.beans.factory.annotation.Autowired;
47+
import org.springframework.context.ConfigurableApplicationContext;
4648
import org.springframework.core.convert.converter.Converter;
4749
import org.springframework.dao.DataAccessException;
4850
import org.springframework.dao.DataIntegrityViolationException;
@@ -70,11 +72,14 @@
7072
import org.springframework.data.mongodb.core.index.IndexInfo;
7173
import org.springframework.data.mongodb.core.mapping.Field;
7274
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
75+
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
76+
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
7377
import org.springframework.data.mongodb.core.query.BasicQuery;
7478
import org.springframework.data.mongodb.core.query.Criteria;
7579
import org.springframework.data.mongodb.core.query.Query;
7680
import org.springframework.data.mongodb.core.query.Update;
7781
import org.springframework.data.util.CloseableIterator;
82+
import org.springframework.test.annotation.DirtiesContext;
7883
import org.springframework.test.context.ContextConfiguration;
7984
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
8085
import org.springframework.util.ObjectUtils;
@@ -114,6 +119,7 @@ public class MongoTemplateTests {
114119

115120
@Autowired MongoTemplate template;
116121
@Autowired MongoDbFactory factory;
122+
@Autowired ConfigurableApplicationContext context;
117123

118124
MongoTemplate mappingTemplate;
119125
org.springframework.data.util.Version mongoVersion;
@@ -3164,6 +3170,28 @@ public void updateShouldWorkForTypesContainingGeoJsonTypes() {
31643170
assertThat(template.findOne(query(where("id").is(wgj.id)), WithGeoJson.class).point, is(equalTo(wgj.point)));
31653171
}
31663172

3173+
/**
3174+
* @see DATAMONGO-1513
3175+
*/
3176+
@Test
3177+
@DirtiesContext
3178+
public void populatesIdsAddedByEventListener() {
3179+
3180+
context.addApplicationListener(new AbstractMongoEventListener<Document>() {
3181+
3182+
@Override
3183+
public void onBeforeSave(BeforeSaveEvent<Document> event) {
3184+
event.getDBObject().put("_id", UUID.randomUUID().toString());
3185+
}
3186+
});
3187+
3188+
Document document = new Document();
3189+
3190+
template.insertAll(Arrays.asList(document));
3191+
3192+
assertThat(document.id, is(notNullValue()));
3193+
}
3194+
31673195
static class DoucmentWithNamedIdField {
31683196

31693197
@Id String someIdKey;

0 commit comments

Comments
 (0)