Skip to content

Commit 13f2472

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 5de9994 commit 13f2472

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
@@ -763,27 +763,33 @@ public void insertAll(Collection<? extends Object> objectsToSave) {
763763
}
764764

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

768-
for (T o : listToSave) {
767+
Map<String, List<T>> elementsByCollection = new HashMap<String, List<T>>();
768+
769+
for (T element : listToSave) {
770+
771+
if (element == null) {
772+
continue;
773+
}
774+
775+
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(element.getClass());
769776

770-
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(o.getClass());
771777
if (entity == null) {
772-
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
773-
+ o.getClass().getName());
778+
throw new InvalidDataAccessApiUsageException("No PersistentEntity information found for " + element.getClass());
774779
}
780+
775781
String collection = entity.getCollection();
782+
List<T> collectionElements = elementsByCollection.get(collection);
776783

777-
List<T> objList = objs.get(collection);
778-
if (null == objList) {
779-
objList = new ArrayList<T>();
780-
objs.put(collection, objList);
784+
if (null == collectionElements) {
785+
collectionElements = new ArrayList<T>();
786+
elementsByCollection.put(collection, collectionElements);
781787
}
782-
objList.add(o);
783788

789+
collectionElements.add(element);
784790
}
785791

786-
for (Map.Entry<String, List<T>> entry : objs.entrySet()) {
792+
for (Map.Entry<String, List<T>> entry : elementsByCollection.entrySet()) {
787793
doInsertBatch(entry.getKey(), entry.getValue(), this.mongoConverter);
788794
}
789795
}

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
@@ -74,6 +74,7 @@
7474
import org.springframework.data.mongodb.core.query.Update;
7575
import org.springframework.test.context.ContextConfiguration;
7676
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
77+
import org.springframework.util.ObjectUtils;
7778
import org.springframework.util.StringUtils;
7879

7980
import com.mongodb.BasicDBObject;
@@ -188,6 +189,7 @@ protected void cleanDb() {
188189
template.dropCollection(DocumentWithDBRefCollection.class);
189190
template.dropCollection(SomeContent.class);
190191
template.dropCollection(SomeTemplate.class);
192+
template.dropCollection(Address.class);
191193
}
192194

193195
@Test
@@ -2740,6 +2742,23 @@ public void insertsAndRemovesBasicDbObjectCorrectly() {
27402742
assertThat(template.findAll(DBObject.class, "collection"), hasSize(0));
27412743
}
27422744

2745+
/**
2746+
* @see DATAMONGO-1207
2747+
*/
2748+
@Test
2749+
public void ignoresNullElementsForInsertAll() {
2750+
2751+
Address newYork = new Address("NY", "New York");
2752+
Address washington = new Address("DC", "Washington");
2753+
2754+
template.insertAll(Arrays.asList(newYork, null, washington));
2755+
2756+
List<Address> result = template.findAll(Address.class);
2757+
2758+
assertThat(result, hasSize(2));
2759+
assertThat(result, hasItems(newYork, washington));
2760+
}
2761+
27432762
static class DoucmentWithNamedIdField {
27442763

27452764
@Id String someIdKey;
@@ -2926,6 +2945,41 @@ static class Address {
29262945

29272946
String state;
29282947
String city;
2948+
2949+
Address() {}
2950+
2951+
Address(String state, String city) {
2952+
this.state = state;
2953+
this.city = city;
2954+
}
2955+
2956+
@Override
2957+
public boolean equals(Object obj) {
2958+
2959+
if (obj == this) {
2960+
return true;
2961+
}
2962+
2963+
if (!(obj instanceof Address)) {
2964+
return false;
2965+
}
2966+
2967+
Address that = (Address) obj;
2968+
2969+
return ObjectUtils.nullSafeEquals(this.city, that.city) && //
2970+
ObjectUtils.nullSafeEquals(this.state, that.state);
2971+
}
2972+
2973+
@Override
2974+
public int hashCode() {
2975+
2976+
int result = 17;
2977+
2978+
result += 31 * ObjectUtils.nullSafeHashCode(this.city);
2979+
result += 31 * ObjectUtils.nullSafeHashCode(this.state);
2980+
2981+
return result;
2982+
}
29292983
}
29302984

29312985
static class VersionedPerson {

0 commit comments

Comments
 (0)