Ensure conversion service actually converts to the correct type
Update `BindConverter` with a guard to ensure that the resulting object is the correct type. Fixes gh-28592
This commit is contained in:
parent
e02803d341
commit
31b0264d94
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -106,7 +106,10 @@ final class BindConverter {
|
|||
for (ConversionService delegate : this.delegates) {
|
||||
try {
|
||||
if (delegate.canConvert(sourceType, targetType)) {
|
||||
return delegate.convert(source, sourceType, targetType);
|
||||
Object converted = delegate.convert(source, sourceType, targetType);
|
||||
if (targetType.getType().isInstance(converted)) {
|
||||
return converted;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ConversionException ex) {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import org.springframework.boot.context.properties.bind.BindException;
|
|||
import org.springframework.boot.context.properties.bind.DefaultValue;
|
||||
import org.springframework.boot.context.properties.bind.validation.BindValidationException;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||
import org.springframework.boot.convert.ApplicationConversionService;
|
||||
import org.springframework.boot.convert.DataSizeUnit;
|
||||
import org.springframework.boot.convert.DurationFormat;
|
||||
import org.springframework.boot.convert.DurationStyle;
|
||||
|
|
@ -1081,6 +1082,15 @@ class ConfigurationPropertiesTests {
|
|||
assertThat(keys.stream().map(ConfigurationPropertyName::toString)).contains("name", "nested.name");
|
||||
}
|
||||
|
||||
@Test // gh-28592
|
||||
void loadWhenBindingWithCustomConverterAndObjectToObjectMethod() {
|
||||
this.context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
|
||||
load(WithCustomConverterAndObjectToObjectMethodConfiguration.class, "test.item=foo");
|
||||
WithCustomConverterAndObjectToObjectMethodProperties bean = this.context
|
||||
.getBean(WithCustomConverterAndObjectToObjectMethodProperties.class);
|
||||
assertThat(bean.getItem().getValue()).isEqualTo("foo");
|
||||
}
|
||||
|
||||
private AnnotationConfigApplicationContext load(Class<?> configuration, String... inlinedProperties) {
|
||||
return load(new Class<?>[] { configuration }, inlinedProperties);
|
||||
}
|
||||
|
|
@ -2710,4 +2720,40 @@ class ConfigurationPropertiesTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(WithCustomConverterAndObjectToObjectMethodProperties.class)
|
||||
static class WithCustomConverterAndObjectToObjectMethodConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConfigurationPropertiesBinding
|
||||
WithObjectToObjectMethodConverter withObjectToObjectMethodConverter() {
|
||||
return new WithObjectToObjectMethodConverter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties("test")
|
||||
static class WithCustomConverterAndObjectToObjectMethodProperties {
|
||||
|
||||
private WithPublicObjectToObjectMethod item;
|
||||
|
||||
WithPublicObjectToObjectMethod getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
void setItem(WithPublicObjectToObjectMethod item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class WithObjectToObjectMethodConverter implements Converter<String, WithPublicObjectToObjectMethod> {
|
||||
|
||||
@Override
|
||||
public WithPublicObjectToObjectMethod convert(String source) {
|
||||
return new WithPublicObjectToObjectMethod(source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.properties;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Data object with a pubic method picked up by the {@code ObjectToObjectConverter}. Used
|
||||
* in {@link ConfigurationPropertiesTests}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class WithPublicObjectToObjectMethod {
|
||||
|
||||
private final String value;
|
||||
|
||||
WithPublicObjectToObjectMethod(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static Optional<WithPublicObjectToObjectMethod> from(String value) {
|
||||
return Optional.of(new WithPublicObjectToObjectMethod(value));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue