Skip to content

Fix CustomConverter conversions. #3581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-3580-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-3580-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-3580-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.0-GH-3580-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ protected <S extends Object> 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)) {
Expand Down Expand Up @@ -1532,9 +1532,17 @@ public MappingMongoConverter with(MongoDatabaseFactory dbFactory) {
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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
T content;
}
Expand Down Expand Up @@ -2899,4 +2944,31 @@ public Person onAfterConvert(Person entity, org.bson.Document document, String c
}
}

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;
}
}
}