Skip to content

Commit 67cf0e6

Browse files
committed
DATAMONGO-1207 - Fixed potential NPE in MongoTemplate.doInsertAll(…).
If a collection containing null values is handed to MongoTempalte.insertAll(…), a NullPointerException was caused by the unguarded attempt to lookup the class of the element. We now explicitly handle this case and skip the element. Some code cleanups in MongoTemplate.doInsertAll(…).
1 parent 21fbcc3 commit 67cf0e6

File tree

2 files changed

+71
-11
lines changed

2 files changed

+71
-11
lines changed

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -841,27 +841,33 @@ public void insertAll(Collection<? extends Object> objectsToSave) {
841841
}
842842

843843
protected <T> void doInsertAll(Collection<? extends T> listToSave, MongoWriter<T> writer) {
844-
Map<String, List<T>> objs = new HashMap<String, List<T>>();
845844

846-
for (T o : listToSave) {
845+
Map<String, List<T>> elementsByCollection = new HashMap<String, List<T>>();
846+
847+
for (T element : listToSave) {
848+
849+
if (element == null) {
850+
continue;
851+
}
852+
853+
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(element.getClass());
847854

848-
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(o.getClass());
849855
if (entity == null) {
850-
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
851-
+ o.getClass().getName());
856+
throw new InvalidDataAccessApiUsageException("No PersistentEntity information found for " + element.getClass());
852857
}
858+
853859
String collection = entity.getCollection();
860+
List<T> collectionElements = elementsByCollection.get(collection);
854861

855-
List<T> objList = objs.get(collection);
856-
if (null == objList) {
857-
objList = new ArrayList<T>();
858-
objs.put(collection, objList);
862+
if (null == collectionElements) {
863+
collectionElements = new ArrayList<T>();
864+
elementsByCollection.put(collection, collectionElements);
859865
}
860-
objList.add(o);
861866

867+
collectionElements.add(element);
862868
}
863869

864-
for (Map.Entry<String, List<T>> entry : objs.entrySet()) {
870+
for (Map.Entry<String, List<T>> entry : elementsByCollection.entrySet()) {
865871
doInsertBatch(entry.getKey(), entry.getValue(), this.mongoConverter);
866872
}
867873
}

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.springframework.data.mongodb.core.query.Update;
7676
import org.springframework.test.context.ContextConfiguration;
7777
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
78+
import org.springframework.util.ObjectUtils;
7879
import org.springframework.util.StringUtils;
7980

8081
import com.mongodb.BasicDBObject;
@@ -190,6 +191,7 @@ protected void cleanDb() {
190191
template.dropCollection(DocumentWithDBRefCollection.class);
191192
template.dropCollection(SomeContent.class);
192193
template.dropCollection(SomeTemplate.class);
194+
template.dropCollection(Address.class);
193195
}
194196

195197
@Test
@@ -2723,6 +2725,23 @@ public void insertsAndRemovesBasicDbObjectCorrectly() {
27232725
assertThat(template.findAll(DBObject.class, "collection"), hasSize(0));
27242726
}
27252727

2728+
/**
2729+
* @see DATAMONGO-1207
2730+
*/
2731+
@Test
2732+
public void ignoresNullElementsForInsertAll() {
2733+
2734+
Address newYork = new Address("NY", "New York");
2735+
Address washington = new Address("DC", "Washington");
2736+
2737+
template.insertAll(Arrays.asList(newYork, null, washington));
2738+
2739+
List<Address> result = template.findAll(Address.class);
2740+
2741+
assertThat(result, hasSize(2));
2742+
assertThat(result, hasItems(newYork, washington));
2743+
}
2744+
27262745
static class DoucmentWithNamedIdField {
27272746

27282747
@Id String someIdKey;
@@ -2909,6 +2928,41 @@ static class Address {
29092928

29102929
String state;
29112930
String city;
2931+
2932+
Address() {}
2933+
2934+
Address(String state, String city) {
2935+
this.state = state;
2936+
this.city = city;
2937+
}
2938+
2939+
@Override
2940+
public boolean equals(Object obj) {
2941+
2942+
if (obj == this) {
2943+
return true;
2944+
}
2945+
2946+
if (!(obj instanceof Address)) {
2947+
return false;
2948+
}
2949+
2950+
Address that = (Address) obj;
2951+
2952+
return ObjectUtils.nullSafeEquals(this.city, that.city) && //
2953+
ObjectUtils.nullSafeEquals(this.state, that.state);
2954+
}
2955+
2956+
@Override
2957+
public int hashCode() {
2958+
2959+
int result = 17;
2960+
2961+
result += 31 * ObjectUtils.nullSafeHashCode(this.city);
2962+
result += 31 * ObjectUtils.nullSafeHashCode(this.state);
2963+
2964+
return result;
2965+
}
29122966
}
29132967

29142968
static class VersionedPerson {

0 commit comments

Comments
 (0)