Browse Source

Fix CustomConverter conversion lookup.

This commit makes sure to fall back to the configured custom converter if no more type specific converter has been registered.

Closes #3580
Original pull request: #3581.
pull/3585/head
Christoph Strobl 5 years ago committed by Mark Paluch
parent
commit
a1a0675976
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 14
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 72
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

14
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

@ -292,7 +292,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -292,7 +292,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
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 class MappingMongoConverter extends AbstractMongoConverter implements App @@ -1532,9 +1532,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return target;
}
private <T extends Object> T doConvert(Object value, Class<? extends T> target) {
return doConvert(value, target, null);
}
@SuppressWarnings("ConstantConditions")
private <T> T doConvert(Object value, Class<T> target) {
return conversionService.convert(value, target);
private <T extends Object> 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);
}
/**

72
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

@ -2383,6 +2383,51 @@ class MappingMongoConverterUnitTests { @@ -2383,6 +2383,51 @@ class MappingMongoConverterUnitTests {
.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> {
T content;
}
@ -2899,4 +2944,31 @@ class MappingMongoConverterUnitTests { @@ -2899,4 +2944,31 @@ class MappingMongoConverterUnitTests {
}
}
static class SubTypeOfGenericType extends GenericType<String> {
}
@ReadingConverter
static class GenericTypeConverter implements Converter<org.bson.Document, GenericType<?>> {
@Override
public GenericType<?> convert(org.bson.Document source) {
GenericType<Object> target = new GenericType<>();
target.content = source.get("value");
return target;
}
}
@ReadingConverter
static class SubTypeOfGenericTypeConverter implements Converter<org.bson.Document, SubTypeOfGenericType> {
@Override
public SubTypeOfGenericType convert(org.bson.Document source) {
SubTypeOfGenericType target = new SubTypeOfGenericType();
target.content = source.getString("value") + "_s";
return target;
}
}
}

Loading…
Cancel
Save