From 17e8837981a5432d41c6ae8a05d5dc5ffc9caf45 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 24 Nov 2023 14:48:39 +0100 Subject: [PATCH] Fix NPE when traversing map. We now use regular iteration instead of the Stream API. Closes: #4567 Original pull request: #4568 --- .../mongodb/core/convert/QueryMapper.java | 23 +++++++++++-------- .../core/convert/UpdateMapperUnitTests.java | 12 ++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 30f8e47a09..5c1d137ccd 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -617,15 +617,20 @@ protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersisten if (source instanceof Map sourceMap) { - return sourceMap.entrySet().stream().collect(Collectors.toMap( - entry -> ObjectUtils.nullSafeToString(converter.convertToMongoType(entry.getKey())), - entry -> { - if (entry.getValue() instanceof Document document) { - return getMappedObject(document, entity); - } - return delegateConvertToMongoType(entry.getValue(), entity); - } - )); + Map map = new LinkedHashMap<>(sourceMap.size(), 1F); + + sourceMap.entrySet().forEach(it -> { + + String key = ObjectUtils.nullSafeToString(converter.convertToMongoType(it.getKey())); + + if (it.getValue() instanceof Document document) { + map.put(key, getMappedObject(document, entity)); + } else { + map.put(key, delegateConvertToMongoType(it.getValue(), entity)); + } + }); + + return map; } return delegateConvertToMongoType(source, entity); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index df1e13aeae..d9c7496138 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -762,6 +762,18 @@ void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration( assertThat(mappedUpdate).doesNotContainKey("$set.concreteMap.jasnah._class"); } + @Test // GH-4567 + void updateShouldAllowNullValuesInMap() { + + Map map = Collections.singletonMap("jasnah", new NestedDocument("kholin")); + + Update update = new Update().set("concreteMap", Collections.singletonMap("jasnah", null)); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithObjectMap.class)); + + assertThat(mappedUpdate).isEqualTo(new Document("$set", new Document("concreteMap", Collections.singletonMap("jasnah", null)))); + } + @Test // DATAMONGO-1250 @SuppressWarnings("unchecked") void mapsUpdateWithBothReadingAndWritingConverterRegistered() {