Skip to content

Commit f782338

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 cb90bfc commit f782338

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
@@ -948,7 +948,9 @@ protected <T> void doInsertBatch(String collectionName, Collection<? extends T>
948948
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc, collectionName));
949949
dbObjectList.add(dbDoc);
950950
}
951-
List<ObjectId> ids = insertDBObjectList(collectionName, dbObjectList);
951+
952+
List<Object> ids = consolidateIdentifiers(insertDBObjectList(collectionName, dbObjectList), dbObjectList);
953+
952954
int i = 0;
953955
for (T obj : batchToSave) {
954956
if (i < ids.size()) {
@@ -1053,6 +1055,8 @@ public Object doInCollection(DBCollection collection) throws MongoException, Dat
10531055
});
10541056
}
10551057

1058+
// TODO: 2.0 - Change method signature to return List<Object> and return all identifiers (DATAMONGO-1513,
1059+
// DATAMONGO-1519)
10561060
protected List<ObjectId> insertDBObjectList(final String collectionName, final List<DBObject> dbDocList) {
10571061
if (dbDocList.isEmpty()) {
10581062
return Collections.emptyList();
@@ -2131,6 +2135,28 @@ private static RuntimeException potentiallyConvertRuntimeException(RuntimeExcept
21312135
return resolved == null ? ex : resolved;
21322136
}
21332137

2138+
/**
2139+
* Returns all identifiers for the given documents. Will augment the given identifiers and fill in only the ones that
2140+
* are {@literal null} currently. This would've been better solved in {@link #insertDBObjectList(String, List)}
2141+
* directly but would require a signature change of that method.
2142+
*
2143+
* @param ids
2144+
* @param documents
2145+
* @return TODO: Remove for 2.0 and change method signature of {@link #insertDBObjectList(String, List)}.
2146+
*/
2147+
private static List<Object> consolidateIdentifiers(List<ObjectId> ids, List<DBObject> documents) {
2148+
2149+
List<Object> result = new ArrayList<Object>(ids.size());
2150+
2151+
for (int i = 0; i < ids.size(); i++) {
2152+
2153+
ObjectId objectId = ids.get(i);
2154+
result.add(objectId == null ? documents.get(i).get(ID_FIELD) : objectId);
2155+
}
2156+
2157+
return result;
2158+
}
2159+
21342160
// Callback implementations
21352161

21362162
/**

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
@@ -37,6 +37,7 @@
3737
import java.util.List;
3838
import java.util.Locale;
3939
import java.util.Map;
40+
import java.util.UUID;
4041

4142
import org.bson.types.ObjectId;
4243
import org.joda.time.DateTime;
@@ -47,6 +48,7 @@
4748
import org.junit.rules.ExpectedException;
4849
import org.junit.runner.RunWith;
4950
import org.springframework.beans.factory.annotation.Autowired;
51+
import org.springframework.context.ConfigurableApplicationContext;
5052
import org.springframework.core.convert.converter.Converter;
5153
import org.springframework.dao.DataAccessException;
5254
import org.springframework.dao.DataIntegrityViolationException;
@@ -74,11 +76,14 @@
7476
import org.springframework.data.mongodb.core.index.IndexInfo;
7577
import org.springframework.data.mongodb.core.mapping.Field;
7678
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
79+
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
80+
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
7781
import org.springframework.data.mongodb.core.query.BasicQuery;
7882
import org.springframework.data.mongodb.core.query.Criteria;
7983
import org.springframework.data.mongodb.core.query.Query;
8084
import org.springframework.data.mongodb.core.query.Update;
8185
import org.springframework.data.util.CloseableIterator;
86+
import org.springframework.test.annotation.DirtiesContext;
8287
import org.springframework.test.context.ContextConfiguration;
8388
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
8489
import org.springframework.util.ObjectUtils;
@@ -123,6 +128,7 @@ public class MongoTemplateTests {
123128

124129
@Autowired MongoTemplate template;
125130
@Autowired MongoDbFactory factory;
131+
@Autowired ConfigurableApplicationContext context;
126132

127133
MongoTemplate mappingTemplate;
128134
org.springframework.data.util.Version mongoVersion;
@@ -3442,6 +3448,28 @@ public void shouldFetchMapOfLazyReferencesCorrectly() {
34423448
assertThat(target.lazyDbRefAnnotatedMap.values(), contains(two, one));
34433449
}
34443450

3451+
/**
3452+
* @see DATAMONGO-1513
3453+
*/
3454+
@Test
3455+
@DirtiesContext
3456+
public void populatesIdsAddedByEventListener() {
3457+
3458+
context.addApplicationListener(new AbstractMongoEventListener<Document>() {
3459+
3460+
@Override
3461+
public void onBeforeSave(BeforeSaveEvent<Document> event) {
3462+
event.getDBObject().put("_id", UUID.randomUUID().toString());
3463+
}
3464+
});
3465+
3466+
Document document = new Document();
3467+
3468+
template.insertAll(Arrays.asList(document));
3469+
3470+
assertThat(document.id, is(notNullValue()));
3471+
}
3472+
34453473
static class TypeWithNumbers {
34463474

34473475
@Id String id;

0 commit comments

Comments
 (0)