Document support for java.util.Duration

Closes gh-12244
This commit is contained in:
Stephane Nicoll 2018-02-27 18:00:36 +01:00
parent 6676967cc1
commit 9ce96fbd89
4 changed files with 187 additions and 3 deletions

View File

@ -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
:dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin
: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-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

View File

@ -1177,8 +1177,8 @@ such as `my.property-name=acme`.
[[boot-features-external-config-conversion]]
==== Properties Conversion
Spring attempts to coerce the external application properties to the right type when it
binds to the `@ConfigurationProperties` beans. If you need custom type conversion, you
Spring Boot attempts to coerce the external application properties to the right type when
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
property editors (through a `CustomEditorConfigurer` bean) or custom `Converters` (with
bean definitions annotated as `@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]]
==== @ConfigurationProperties Validation
Spring Boot attempts to validate `@ConfigurationProperties` classes whenever they are
@ -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
logging but leaves the underlying log implementation open. Default configurations are
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
http://logback.qos.ch/[Logback]. In each case, loggers are pre-configured to use console
output with optional file output also available.

View File

@ -0,0 +1,56 @@
/*
* 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[]

View File

@ -0,0 +1,83 @@
/*
* 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 {
}
}