Allow DurationFormat and PeriodFormat to be used on parameters
See gh-22646
This commit is contained in:
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,7 @@ import java.time.Duration;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Target({ ElementType.FIELD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DurationFormat {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.time.Period;
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Target({ ElementType.FIELD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
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.source.ConfigurationPropertyName;
|
||||
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.PeriodFormat;
|
||||
import org.springframework.boot.convert.PeriodStyle;
|
||||
import org.springframework.boot.convert.PeriodUnit;
|
||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
@@ -808,6 +812,53 @@ class ConfigurationPropertiesTests {
|
||||
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
|
||||
void loadWhenBindingToConstructorParametersShouldValidate() {
|
||||
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
|
||||
@ConfigurationProperties(prefix = "test")
|
||||
@Validated
|
||||
@@ -2035,6 +2111,11 @@ class ConfigurationPropertiesTests {
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties(ConstructorParameterWithFormatProperties.class)
|
||||
static class ConstructorParameterWithFormatConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties(ConstructorParameterValidatedProperties.class)
|
||||
static class ConstructorParameterValidationConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user