Commit 9ce96fbd authored by Stephane Nicoll's avatar Stephane Nicoll

Document support for java.util.Duration

Closes gh-12244
parent 6676967c
...@@ -36,6 +36,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson; ...@@ -36,6 +36,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
:dc-spring-boot-test-autoconfigure: {dc-root}/org/springframework/boot/test/autoconfigure :dc-spring-boot-test-autoconfigure: {dc-root}/org/springframework/boot/test/autoconfigure
:dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin :dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin
:dependency-management-plugin-documentation: {dependency-management-plugin}/blob/master/README.md :dependency-management-plugin-documentation: {dependency-management-plugin}/blob/master/README.md
:java-javadoc: https://docs.oracle.com/javase/8/docs/api/
:spring-boot-actuator-api: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/actuator-api/ :spring-boot-actuator-api: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/actuator-api/
:spring-boot-maven-plugin-site: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/maven-plugin :spring-boot-maven-plugin-site: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/maven-plugin
:spring-boot-gradle-plugin: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/gradle-plugin :spring-boot-gradle-plugin: https://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/gradle-plugin
......
...@@ -1177,8 +1177,8 @@ such as `my.property-name=acme`. ...@@ -1177,8 +1177,8 @@ such as `my.property-name=acme`.
[[boot-features-external-config-conversion]] [[boot-features-external-config-conversion]]
==== Properties Conversion ==== Properties Conversion
Spring attempts to coerce the external application properties to the right type when it Spring Boot attempts to coerce the external application properties to the right type when
binds to the `@ConfigurationProperties` beans. If you need custom type conversion, you it binds to the `@ConfigurationProperties` beans. If you need custom type conversion, you
can provide a `ConversionService` bean (with a bean named `conversionService`) or custom can provide a `ConversionService` bean (with a bean named `conversionService`) or custom
property editors (through a `CustomEditorConfigurer` bean) or custom `Converters` (with property editors (through a `CustomEditorConfigurer` bean) or custom `Converters` (with
bean definitions annotated as `@ConfigurationPropertiesBinding`). bean definitions annotated as `@ConfigurationPropertiesBinding`).
...@@ -1191,6 +1191,50 @@ only rely on custom converters qualified with `@ConfigurationPropertiesBinding`. ...@@ -1191,6 +1191,50 @@ only rely on custom converters qualified with `@ConfigurationPropertiesBinding`.
[[boot-features-external-config-conversion-duration]]
===== Converting durations
Spring Boot has dedicated support for expressing durations. If you expose a
`java.time.Duration` property, the following formats in application properties are
available:
* A regular `long` representation (using milliseconds as the default unit unless a
`@DefaultUnit` has been specified)
* The standard ISO-8601 format
{java-javadoc}/java/time/Duration.html#parse-java.lang.CharSequence-[used by
`java.util.Duration`]
* A more readable format where the value and the unit are coupled (e.g. `10s` means 10
seconds)
Consider the following example:
[source,java,indent=0]
----
include::{code-examples}/context/properties/bind/AppSystemProperties.java[tag=example]
----
To specify a session timeout of 30 seconds, `30`, `PT30S` and `30s` are all equivalent. A
read timeout of 500ms can be specified in any of the following form: `500`, `PT0.5S` and
`500ms`.
You can also use any of the supported unit. These are:
* `ns` for nanoseconds
* `ms` for milliseconds
* `s` for seconds
* `m` for minutes
* `h` for hours
* `d` for days
The default unit is milliseconds and can be overridden using `@DefaultUnit` as illustrated
in the sample above.
TIP: If you are upgrading from a previous version that is simply using `Long` to express
the duration, make sure to define the unit (using `@DefaultUnit`) if it isn't
milliseconds alongside the switch to `Duration`. Doing so gives a transparent upgrade path
while supporting a much richer format.
[[boot-features-external-config-validation]] [[boot-features-external-config-validation]]
==== @ConfigurationProperties Validation ==== @ConfigurationProperties Validation
Spring Boot attempts to validate `@ConfigurationProperties` classes whenever they are Spring Boot attempts to validate `@ConfigurationProperties` classes whenever they are
...@@ -1387,7 +1431,7 @@ See "<<boot-features-external-config-profile-specific-properties>>" for details. ...@@ -1387,7 +1431,7 @@ See "<<boot-features-external-config-profile-specific-properties>>" for details.
Spring Boot uses http://commons.apache.org/logging[Commons Logging] for all internal Spring Boot uses http://commons.apache.org/logging[Commons Logging] for all internal
logging but leaves the underlying log implementation open. Default configurations are logging but leaves the underlying log implementation open. Default configurations are
provided for provided for
https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html[Java Util {java-javadoc}/java/util/logging/package-summary.html[Java Util
Logging], http://logging.apache.org/log4j/2.x/[Log4J2], and Logging], http://logging.apache.org/log4j/2.x/[Log4J2], and
http://logback.qos.ch/[Logback]. In each case, loggers are pre-configured to use console http://logback.qos.ch/[Logback]. In each case, loggers are pre-configured to use console
output with optional file output also available. output with optional file output also available.
......
/*
* Copyright 2012-2018 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
*
* http://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.docs.context.properties.bind;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;
/**
* A {@link ConfigurationProperties} example that uses {@link Duration}.
*
* @author Stephane Nicoll
*/
// tag::example[]
@ConfigurationProperties("app.system")
public class AppSystemProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
public Duration getSessionTimeout() {
return this.sessionTimeout;
}
public void setSessionTimeout(Duration sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public Duration getReadTimeout() {
return this.readTimeout;
}
public void setReadTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
}
}
// end::example[]
/*
* Copyright 2012-2018 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
*
* http://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.docs.context.properties.bind;
import java.time.Duration;
import java.util.function.Consumer;
import org.junit.Test;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link AppSystemProperties}.
*
* @author Stephane Nicoll
*/
public class AppSystemPropertiesTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class);
@Test
public void bindWithDefaultUnit() {
this.contextRunner.withPropertyValues("app.system.session-timeout=40",
"app.system.read-timeout=5000").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofSeconds(40));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(5000));
}));
}
@Test
public void bindWithExplicitUnit() {
this.contextRunner.withPropertyValues("app.system.session-timeout=1h",
"app.system.read-timeout=5s").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofMinutes(60));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(5000));
}));
}
@Test
public void bindWithIso8601Format() {
this.contextRunner.withPropertyValues("app.system.session-timeout=PT15S",
"app.system.read-timeout=PT0.5S").run(assertBinding(p -> {
assertThat(p.getSessionTimeout()).isEqualTo(Duration.ofSeconds(15));
assertThat(p.getReadTimeout()).isEqualTo(Duration.ofMillis(500));
}));
}
private ContextConsumer<AssertableApplicationContext> assertBinding(
Consumer<AppSystemProperties> appSystemProperties) {
return (context) -> {
assertThat(context).hasSingleBean(AppSystemProperties.class);
appSystemProperties.accept(context.getBean(AppSystemProperties.class));
};
}
@Configuration
@EnableConfigurationProperties(AppSystemProperties.class)
static class Config {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment