From 390b00d5fed52a33aa8b567284ea6623c7f59608 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 13 Jul 2018 10:17:05 +0200 Subject: [PATCH] DATAMONGO-2026 - Fix id property resolution for immutable objects. We now make sure id properties used as persistence constructor arguments are no longer set via the property accessor, but during object instantiation. Previous to this change this caused an UnsupportedOperationException. Original pull request: #586. --- .../core/convert/MappingMongoConverter.java | 11 ++++++++--- .../convert/MappingMongoConverterUnitTests.java | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index 23df7f06e..73178e96a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -282,10 +282,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App // make sure id property is set before all other properties Object idValue = null; - if (idProperty != null && documentAccessor.hasValue(idProperty)) { + if (idProperty != null) { - idValue = readIdValue(path, evaluator, idProperty, documentAccessor); - accessor.setProperty(idProperty, idValue); + if (idProperty.isImmutable() && entity.isConstructorArgument(idProperty)) { + idValue = accessor.getProperty(idProperty); + } else if (documentAccessor.hasValue(idProperty)) { + + idValue = readIdValue(path, evaluator, idProperty, documentAccessor); + accessor.setProperty(idProperty, idValue); + } } ObjectPath currentPath = path.push(instance, entity, idValue != null ? bson.get(idProperty.getFieldName()) : null); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 427d41a7d..f7890c8fa 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -1882,6 +1882,15 @@ public class MappingMongoConverterUnitTests { assertThat(result.id).isEqualTo("foo"); assertThat(result.witherUsed).isTrue(); } + @Test // DATAMONGO-2026 + public void readsImmutableObjectWithConstructorIdPropertyCorrectly() { + + org.bson.Document source = new org.bson.Document("_id", "spring").append("value", "data"); + + ImmutableObjectWithIdConstructorPropertyAndNoIdWitherMethod target = converter.read(ImmutableObjectWithIdConstructorPropertyAndNoIdWitherMethod.class, source); + assertThat(target.id).isEqualTo("spring"); + assertThat(target.value).isEqualTo("data"); + } static class GenericType { T content; @@ -2265,6 +2274,7 @@ public class MappingMongoConverterUnitTests { } static class ImmutableObject { + final String id; final String name; final boolean witherUsed; @@ -2303,4 +2313,11 @@ public class MappingMongoConverterUnitTests { return witherUsed; } } + + @RequiredArgsConstructor + static class ImmutableObjectWithIdConstructorPropertyAndNoIdWitherMethod { + + final @Id String id; + String value; + } }