diff --git a/pom.xml b/pom.xml
index 828f56af2e..649330214d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 3.2.0-SNAPSHOT
+ 3.2.0-GH-3580-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index f0fbb601c8..dad8f373c9 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 3.2.0-SNAPSHOT
+ 3.2.0-GH-3580-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 1a17321782..a29a7de9ac 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-mongodb-parent
- 3.2.0-SNAPSHOT
+ 3.2.0-GH-3580-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 0248517caf..3ddebab990 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 3.2.0-SNAPSHOT
+ 3.2.0-GH-3580-SNAPSHOT
../pom.xml
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 33586de368..8cc823a0b8 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
@@ -292,7 +292,7 @@ protected S readDocument(ConversionContext context, Bson bson
Class extends S> rawType = typeToRead.getType();
if (conversions.hasCustomReadTarget(bson.getClass(), rawType)) {
- return doConvert(bson, rawType);
+ return doConvert(bson, rawType, typeHint.getType());
}
if (Document.class.isAssignableFrom(rawType)) {
@@ -1532,9 +1532,17 @@ public MappingMongoConverter with(MongoDatabaseFactory dbFactory) {
return target;
}
+ private T doConvert(Object value, Class extends T> target) {
+ return doConvert(value, target, null);
+ }
+
@SuppressWarnings("ConstantConditions")
- private T doConvert(Object value, Class target) {
- return conversionService.convert(value, target);
+ private T doConvert(Object value, Class extends T> target, @Nullable Class extends T> fallback) {
+
+ if(conversionService.canConvert(value.getClass(), target) || fallback == null) {
+ return conversionService.convert(value, target);
+ }
+ return conversionService.convert(value, fallback);
}
/**
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 ffad28b231..db3a4e1b19 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
@@ -2383,6 +2383,51 @@ void writeEmbeddedTypeWithComplexValue() {
.doesNotContainKey("address.city");
}
+ @Test // GH-3580
+ void shouldFallbackToConfiguredCustomConversionTargetOnRead() {
+
+ GenericTypeConverter genericTypeConverter = spy(new GenericTypeConverter());
+
+ converter = new MappingMongoConverter(resolver, mappingContext);
+ converter.setCustomConversions(MongoCustomConversions.create(it -> {
+ it.registerConverter(genericTypeConverter);
+ }));
+ converter.afterPropertiesSet();
+
+ org.bson.Document source = new org.bson.Document("_class", SubTypeOfGenericType.class.getName()).append("value",
+ "v1");
+ GenericType target = converter.read(GenericType.class, source);
+
+ assertThat(target).isInstanceOf(GenericType.class);
+ assertThat(target.content).isEqualTo("v1");
+
+ verify(genericTypeConverter).convert(eq(source));
+ }
+
+ @Test // GH-3580
+ void shouldUseMostConcreteCustomConversionTargetOnRead() {
+
+ GenericTypeConverter genericTypeConverter = spy(new GenericTypeConverter());
+ SubTypeOfGenericTypeConverter subTypeOfGenericTypeConverter = spy(new SubTypeOfGenericTypeConverter());
+
+ converter = new MappingMongoConverter(resolver, mappingContext);
+ converter.setCustomConversions(MongoCustomConversions.create(it -> {
+ it.registerConverter(genericTypeConverter);
+ it.registerConverter(subTypeOfGenericTypeConverter);
+ }));
+ converter.afterPropertiesSet();
+
+ org.bson.Document source = new org.bson.Document("_class", SubTypeOfGenericType.class.getName()).append("value",
+ "v1");
+ GenericType target = converter.read(GenericType.class, source);
+
+ assertThat(target).isInstanceOf(SubTypeOfGenericType.class);
+ assertThat(target.content).isEqualTo("v1_s");
+
+ verify(genericTypeConverter, never()).convert(any());
+ verify(subTypeOfGenericTypeConverter).convert(eq(source));
+ }
+
static class GenericType {
T content;
}
@@ -2899,4 +2944,31 @@ public Person onAfterConvert(Person entity, org.bson.Document document, String c
}
}
+ static class SubTypeOfGenericType extends GenericType {
+
+ }
+
+ @ReadingConverter
+ static class GenericTypeConverter implements Converter> {
+
+ @Override
+ public GenericType> convert(org.bson.Document source) {
+
+ GenericType