Allow DurationFormat and PeriodFormat to be used on parameters

See gh-22646
pull/22681/head
dreis2211 4 years ago committed by Andy Wilkinson
parent c7bfc01bab
commit 914452b2cc

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -30,7 +30,7 @@ import java.time.Duration;
* @author Phillip Webb * @author Phillip Webb
* @since 2.0.0 * @since 2.0.0
*/ */
@Target(ElementType.FIELD) @Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface DurationFormat { public @interface DurationFormat {

@ -31,7 +31,7 @@ import java.time.Period;
* @author Edson Chávez * @author Edson Chávez
* @since 2.3.0 * @since 2.3.0
*/ */
@Target(ElementType.FIELD) @Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface PeriodFormat { public @interface PeriodFormat {

@ -56,7 +56,11 @@ import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.context.properties.bind.validation.BindValidationException; import org.springframework.boot.context.properties.bind.validation.BindValidationException;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.convert.DataSizeUnit; import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.boot.convert.DurationFormat;
import org.springframework.boot.convert.DurationStyle;
import org.springframework.boot.convert.DurationUnit; import org.springframework.boot.convert.DurationUnit;
import org.springframework.boot.convert.PeriodFormat;
import org.springframework.boot.convert.PeriodStyle;
import org.springframework.boot.convert.PeriodUnit; import org.springframework.boot.convert.PeriodUnit;
import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.CapturedOutput;
import org.springframework.boot.testsupport.system.OutputCaptureExtension; import org.springframework.boot.testsupport.system.OutputCaptureExtension;
@ -808,6 +812,53 @@ class ConfigurationPropertiesTests {
assertThat(bean.getPeriod()).isEqualTo(Period.ofYears(4)); assertThat(bean.getPeriod()).isEqualTo(Period.ofYears(4));
} }
@Test
void loadWhenBindingToConstructorParametersWithCustomDataFormatShouldBind() {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("test.duration", "12d");
source.put("test.period", "13y");
sources.addLast(new MapPropertySource("test", source));
load(ConstructorParameterWithFormatConfiguration.class);
ConstructorParameterWithFormatProperties bean = this.context
.getBean(ConstructorParameterWithFormatProperties.class);
assertThat(bean.getDuration()).isEqualTo(Duration.ofDays(12));
assertThat(bean.getPeriod()).isEqualTo(Period.ofYears(13));
}
@Test
void loadWhenBindingToConstructorParametersWithNotMatchingCustomDurationFormatShouldFail() {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("test.duration", "P12D");
sources.addLast(new MapPropertySource("test", source));
assertThatExceptionOfType(Exception.class)
.isThrownBy(() -> load(ConstructorParameterWithFormatConfiguration.class)).satisfies((ex) -> {
assertThat(ex).hasCauseInstanceOf(BindException.class);
});
}
@Test
void loadWhenBindingToConstructorParametersWithNotMatchingCustomPeriodFormatShouldFail() {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("test.period", "P12D");
sources.addLast(new MapPropertySource("test", source));
assertThatExceptionOfType(Exception.class)
.isThrownBy(() -> load(ConstructorParameterWithFormatConfiguration.class)).satisfies((ex) -> {
assertThat(ex).hasCauseInstanceOf(BindException.class);
});
}
@Test
void loadWhenBindingToConstructorParametersWithDefaultDataFormatShouldBind() {
load(ConstructorParameterWithFormatConfiguration.class);
ConstructorParameterWithFormatProperties bean = this.context
.getBean(ConstructorParameterWithFormatProperties.class);
assertThat(bean.getDuration()).isEqualTo(Duration.ofDays(2));
assertThat(bean.getPeriod()).isEqualTo(Period.ofYears(3));
}
@Test @Test
void loadWhenBindingToConstructorParametersShouldValidate() { void loadWhenBindingToConstructorParametersShouldValidate() {
assertThatExceptionOfType(Exception.class) assertThatExceptionOfType(Exception.class)
@ -2007,6 +2058,31 @@ class ConfigurationPropertiesTests {
} }
@ConstructorBinding
@ConfigurationProperties(prefix = "test")
static class ConstructorParameterWithFormatProperties {
private final Duration duration;
private final Period period;
ConstructorParameterWithFormatProperties(
@DefaultValue("2d") @DurationFormat(DurationStyle.SIMPLE) Duration duration,
@DefaultValue("3y") @PeriodFormat(PeriodStyle.SIMPLE) Period period) {
this.duration = duration;
this.period = period;
}
Duration getDuration() {
return this.duration;
}
Period getPeriod() {
return this.period;
}
}
@ConstructorBinding @ConstructorBinding
@ConfigurationProperties(prefix = "test") @ConfigurationProperties(prefix = "test")
@Validated @Validated
@ -2035,6 +2111,11 @@ class ConfigurationPropertiesTests {
} }
@EnableConfigurationProperties(ConstructorParameterWithFormatProperties.class)
static class ConstructorParameterWithFormatConfiguration {
}
@EnableConfigurationProperties(ConstructorParameterValidatedProperties.class) @EnableConfigurationProperties(ConstructorParameterValidatedProperties.class)
static class ConstructorParameterValidationConfiguration { static class ConstructorParameterValidationConfiguration {

Loading…
Cancel
Save