diff --git a/ci/images/get-docker-url.sh b/ci/images/get-docker-url.sh index de0e6326126e..fae9032a9e7f 100755 --- a/ci/images/get-docker-url.sh +++ b/ci/images/get-docker-url.sh @@ -1,5 +1,5 @@ #!/bin/bash set -e -version="20.10.13" +version="20.10.14" echo "https://download.docker.com/linux/static/stable/x86_64/docker-$version.tgz"; diff --git a/ci/images/get-jdk-url.sh b/ci/images/get-jdk-url.sh index c959027b4ded..4d11c3418e7c 100755 --- a/ci/images/get-jdk-url.sh +++ b/ci/images/get-jdk-url.sh @@ -12,7 +12,7 @@ case "$1" in echo "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz" ;; java18) - echo "https://github.com/adoptium/temurin18-binaries/releases/download/jdk18-2022-03-17-09-00-beta/OpenJDK18-jdk_x64_linux_hotspot_2022-03-17-09-00.tar.gz" + echo "https://github.com/adoptium/temurin18-binaries/releases/download/jdk-18%2B36/OpenJDK18U-jdk_x64_linux_hotspot_18_36.tar.gz" ;; *) echo $"Unknown java version" diff --git a/ci/scripts/detect-jdk-updates.sh b/ci/scripts/detect-jdk-updates.sh index e7cc0968cd38..3d67c7773ea6 100755 --- a/ci/scripts/detect-jdk-updates.sh +++ b/ci/scripts/detect-jdk-updates.sh @@ -21,7 +21,7 @@ case "$JDK_VERSION" in ISSUE_TITLE="Upgrade Java 17 version in CI image" ;; java18) - BASE_URL="https://api.adoptium.net/v3/assets/feature_releases/18/ea" + BASE_URL="https://api.adoptium.net/v3/assets/feature_releases/18/ga" ISSUE_TITLE="Upgrade Java 18 version in CI image" ;; *) diff --git a/gradle.properties b/gradle.properties index d42bcbe13f6f..e9bc9e6512d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=2.6.5-SNAPSHOT +version=2.6.6 org.gradle.caching=true org.gradle.parallel=true diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxProperties.java index 2d927d34fe06..ea4adb908203 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 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. @@ -31,6 +31,11 @@ @ConfigurationProperties(prefix = "management.metrics.export.jmx") public class JmxProperties { + /** + * Whether exporting of metrics to this backend is enabled. + */ + private boolean enabled = true; + /** * Metrics JMX domain name. */ @@ -57,4 +62,12 @@ public void setStep(Duration step) { this.step = step; } + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java index 3d3013665070..41b7845f62e4 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 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. @@ -36,6 +36,11 @@ @ConfigurationProperties(prefix = "management.metrics.export.prometheus") public class PrometheusProperties { + /** + * Whether exporting of metrics to this backend is enabled. + */ + private boolean enabled = true; + /** * Whether to enable publishing descriptions as part of the scrape payload to * Prometheus. Turn this off to minimize the amount of data sent on each scrape. @@ -82,6 +87,14 @@ public void setStep(Duration step) { this.step = step; } + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + public Pushgateway getPushgateway() { return this.pushgateway; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleProperties.java index 5433ea65107a..8d4a1e263d02 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 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. @@ -34,6 +34,11 @@ @ConfigurationProperties(prefix = "management.metrics.export.simple") public class SimpleProperties { + /** + * Whether exporting of metrics to this backend is enabled. + */ + private boolean enabled = true; + /** * Step size (i.e. reporting frequency) to use. */ @@ -44,6 +49,14 @@ public class SimpleProperties { */ private CountingMode mode = CountingMode.CUMULATIVE; + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + public Duration getStep() { return this.step; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index cf5e58d7c48a..76da606527cf 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,4 +1,5 @@ { + "groups": [], "properties": [ { "name": "info", @@ -332,13 +333,6 @@ "reason": "Instead, filter 'process.uptime' and 'process.start.time' metrics." } }, - { - "name": "management.metrics.system.diskspace.paths", - "type": "java.util.List", - "defaultValue": [ - "." - ] - }, { "name": "management.metrics.export.appoptics.num-threads", "type": "java.lang.Integer", @@ -433,12 +427,6 @@ "level": "error" } }, - { - "name": "management.metrics.export.jmx.enabled", - "type": "java.lang.Boolean", - "description": "Whether exporting of metrics to JMX is enabled.", - "defaultValue": true - }, { "name": "management.metrics.export.kairos.num-threads", "type": "java.lang.Integer", @@ -456,12 +444,6 @@ "level": "error" } }, - { - "name": "management.metrics.export.prometheus.enabled", - "type": "java.lang.Boolean", - "description": "Whether exporting of metrics to Prometheus is enabled.", - "defaultValue": true - }, { "name": "management.metrics.export.prometheus.histogram-flavor", "defaultValue": "prometheus" @@ -479,12 +461,6 @@ "level": "error" } }, - { - "name": "management.metrics.export.simple.enabled", - "type": "java.lang.Boolean", - "description": "Whether, in the absence of any other exporter, exporting of metrics to an in-memory backend is enabled.", - "defaultValue": true - }, { "name": "management.metrics.export.simple.mode", "defaultValue": "cumulative" @@ -544,6 +520,13 @@ "description": "Whether to enable Mongo connection pool metrics.", "defaultValue": true }, + { + "name": "management.metrics.system.diskspace.paths", + "type": "java.util.List", + "defaultValue": [ + "." + ] + }, { "name": "management.metrics.web.client.request.autotime.enabled", "description": "Whether to automatically time web client requests.", diff --git a/spring-boot-project/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json index c50a6d86e8d1..cd08d79f2272 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,4 +1,5 @@ { + "groups": [], "properties": [ { "name": "management.endpoints.migrate-legacy-ids", @@ -6,5 +7,6 @@ "description": "Whether to transparently migrate legacy endpoint IDs.", "defaultValue": false } - ] + ], + "hints": [] } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheServletWebConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheServletWebConfiguration.java index 0ff0462802a4..03852a80e807 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheServletWebConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache/MustacheServletWebConfiguration.java @@ -18,6 +18,7 @@ import com.samskivert.mustache.Mustache.Compiler; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -29,6 +30,7 @@ @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) +@ConditionalOnClass(MustacheViewResolver.class) class MustacheServletWebConfiguration { @Bean diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 0e6aa32343c3..f2c66bfb4aae 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,4 +1,5 @@ { + "groups": [], "properties": [ { "name": "server.compression.enabled", @@ -514,6 +515,14 @@ "level": "error" } }, + { + "name": "spring.data.cassandra.pool.heartbeat-interval", + "defaultValue": "30s" + }, + { + "name": "spring.data.cassandra.pool.idle-timeout", + "defaultValue": "5s" + }, { "name": "spring.data.cassandra.pool.max-queue-size", "type": "java.lang.Integer", @@ -549,14 +558,14 @@ "name": "spring.data.cassandra.request.page-size", "defaultValue": 5000 }, - { - "name": "spring.data.cassandra.request.timeout", - "defaultValue": "2s" - }, { "name": "spring.data.cassandra.request.throttler.type", "defaultValue": "none" }, + { + "name": "spring.data.cassandra.request.timeout", + "defaultValue": "2s" + }, { "name": "spring.data.cassandra.retry-policy", "type": "java.lang.Class", @@ -565,14 +574,6 @@ "level": "error" } }, - { - "name": "spring.data.cassandra.pool.heartbeat-interval", - "defaultValue": "30s" - }, - { - "name": "spring.data.cassandra.pool.idle-timeout", - "defaultValue": "5s" - }, { "name": "spring.data.couchbase.consistency", "type": "org.springframework.data.couchbase.core.query.Consistency", @@ -1641,6 +1642,10 @@ "name": "spring.neo4j.uri", "defaultValue": "bolt://localhost:7687" }, + { + "name": "spring.netty.leak-detection", + "defaultValue": "simple" + }, { "name": "spring.quartz.jdbc.comment-prefix", "defaultValue": [ @@ -2026,10 +2031,6 @@ "name": "spring.webservices.wsdl-locations", "type": "java.util.List", "description": "Comma-separated list of locations of WSDLs and accompanying XSDs to be exposed as beans." - }, - { - "name": "spring.netty.leak-detection", - "defaultValue": "simple" } ], "hints": [ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java index 123b66f02794..3290c1235a4e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayPropertiesTests.java @@ -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. @@ -111,8 +111,8 @@ void expectedPropertiesAreManaged() { ignoreProperties(properties, "url", "driverClassName", "user", "password", "enabled", "checkLocation", "createDataSource"); // High level object we can't set with properties - ignoreProperties(configuration, "callbacks", "classLoader", "dataSource", "javaMigrations", - "javaMigrationClassProvider", "resourceProvider", "resolvers"); + ignoreProperties(configuration, "callbacks", "dataSource", "javaMigrations", "javaMigrationClassProvider", + "resourceProvider", "resolvers"); // Properties we don't want to expose ignoreProperties(configuration, "resolversAsClassNames", "callbacksAsClassNames", "loggers", "driver"); // Handled by the conversion service diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationWithoutWebMvcTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationWithoutWebMvcTests.java new file mode 100644 index 000000000000..be2a47669ef0 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationWithoutWebMvcTests.java @@ -0,0 +1,45 @@ +/* + * 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.autoconfigure.mustache; + +import com.samskivert.mustache.Mustache; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.testsupport.classpath.ClassPathExclusions; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MustacheAutoConfiguration} without Spring MVC on the class path. + * + * @author Andy Wilkinson + */ +@ClassPathExclusions("spring-webmvc-*.jar") +class MustacheAutoConfigurationWithoutWebMvcTests { + + @Test + void registerBeansForServletAppWithoutMvc() { + new WebApplicationContextRunner().withConfiguration(AutoConfigurations.of(MustacheAutoConfiguration.class)) + .run((context) -> { + assertThat(context).hasSingleBean(Mustache.Compiler.class); + assertThat(context).hasSingleBean(MustacheResourceTemplateLoader.class); + }); + } + +} diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index caa8d3a88b87..e4754063d4a6 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -548,7 +548,7 @@ bom { ] } } - library("Jackson Bom", "2.13.2") { + library("Jackson Bom", "2.13.2.20220328") { group("com.fasterxml.jackson") { imports = [ "jackson-bom" @@ -1699,7 +1699,7 @@ bom { ] } } - library("Spring Framework", "5.3.17") { + library("Spring Framework", "5.3.18") { group("org.springframework") { imports = [ "spring-framework-bom" diff --git a/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 78be077d7783..f852a8ca6048 100644 --- a/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,4 +1,5 @@ { + "groups": [], "properties": [ { "name": "spring.devtools.add-properties", @@ -6,5 +7,6 @@ "description": "Whether to enable development property defaults.", "defaultValue": true } - ] + ], + "hints": [] } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/external-config.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/external-config.adoc index 02b585e72b21..60e1bd74c904 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/external-config.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/external-config.adoc @@ -726,8 +726,10 @@ In this case, unless your record has multiple constructors, there is no need to Nested members of a `@ConstructorBinding` class (such as `Security` in the example above) will also be bound through their constructor. -Default values can be specified using `@DefaultValue` and the same conversion service will be applied to coerce the `String` value to the target type of a missing property. -By default, if no properties are bound to `Security`, the `MyProperties` instance will contain a `null` value for `security`. +Default values can be specified using `@DefaultValue` on a constructor parameter or, when using Java 16 or later, a record component. +The conversion service will be applied to coerce the `String` value to the target type of a missing property. + +Referring to the previous example, if no properties are bound to `Security`, the `MyProperties` instance will contain a `null` value for `security`. If you wish you return a non-null instance of `Security` even when no properties are bound to it, you can use an empty `@DefaultValue` annotation to do so: [source,java,indent=0,subs="verbatim"] diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java index 756d4b9a4ca5..6114aea6ba4a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessorTests.java @@ -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. @@ -425,6 +425,27 @@ void explicityBoundRecordProperties(@TempDir File temp) throws IOException { assertThat(metadata).has(Metadata.withProperty("explicit.some-integer")); } + @Test + @EnabledForJreRange(min = JRE.JAVA_16) + void explicitlyBoundRecordPropertiesWithDefaultValues(@TempDir File temp) throws IOException { + File exampleRecord = new File(temp, "ExampleRecord.java"); + try (PrintWriter writer = new PrintWriter(new FileWriter(exampleRecord))) { + writer.println("@org.springframework.boot.configurationsample.ConstructorBinding"); + writer.println( + "@org.springframework.boot.configurationsample.ConfigurationProperties(\"record.defaults\")"); + writer.println("public record ExampleRecord("); + writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"An1s9n\") String someString,"); + writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"594\") Integer someInteger"); + writer.println(") {"); + writer.println("}"); + } + ConfigurationMetadata metadata = compile(exampleRecord); + assertThat(metadata) + .has(Metadata.withProperty("record.defaults.some-string", String.class).withDefaultValue("An1s9n")); + assertThat(metadata) + .has(Metadata.withProperty("record.defaults.some-integer", Integer.class).withDefaultValue(594)); + } + @Test @EnabledForJreRange(min = JRE.JAVA_16) void implicitlyBoundRecordProperties(@TempDir File temp) throws IOException { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java index 7ca17d55347d..edd8fa710e57 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/ResolveMainClassName.java @@ -91,8 +91,8 @@ public void setClasspath(FileCollection classpath) { } /** - * Sets the classpath to include in the archive. The given {@code classpath} is - * evaluated as per {@link Project#files(Object...)}. + * Sets the classpath that the task will examine when resolving the main class name. + * The given {@code classpath} is evaluated as per {@link Project#files(Object...)}. * @param classpath the classpath * @since 2.5.10 */ diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java index 6c7128e89590..3d6cf545fa79 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/CookieSameSiteSupplier.java @@ -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. @@ -20,9 +20,6 @@ import java.util.function.Supplier; import java.util.regex.Pattern; -/** - * @author Phillip Webb - */ import javax.servlet.http.Cookie; import org.springframework.boot.web.server.Cookie.SameSite; diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 57ba2fd3ee40..e00743330ce9 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -13,12 +13,6 @@ "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", "defaultValue": false }, - { - "name": "logging.config", - "type": "java.lang.String", - "description": "Location of the logging configuration file. For instance, `classpath:logback.xml` for Logback.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener" - }, { "name": "logging.charset.console", "type": "java.nio.charset.Charset", @@ -29,6 +23,12 @@ "type": "java.nio.charset.Charset", "description": "Charset to use for file output." }, + { + "name": "logging.config", + "type": "java.lang.String", + "description": "Location of the logging configuration file. For instance, `classpath:logback.xml` for Logback.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener" + }, { "name": "logging.exception-conversion-word", "type": "java.lang.String", @@ -45,6 +45,36 @@ "level": "error" } }, + { + "name": "logging.file.clean-history-on-start", + "type": "java.lang.Boolean", + "description": "Whether to clean the archive log files on startup. Only supported with the default logback setup.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": false, + "deprecation": { + "replacement": "logging.logback.rollingpolicy.clean-history-on-start" + } + }, + { + "name": "logging.file.max-history", + "type": "java.lang.Integer", + "description": "Maximum number of archive log files to keep. Only supported with the default logback setup.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": 7, + "deprecation": { + "replacement": "logging.logback.rollingpolicy.max-history" + } + }, + { + "name": "logging.file.max-size", + "type": "org.springframework.util.unit.DataSize", + "description": "Maximum log file size. Only supported with the default logback setup.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": "10MB", + "deprecation": { + "replacement": "logging.logback.rollingpolicy.max-file-size" + } + }, { "name": "logging.file.name", "type": "java.lang.String", @@ -57,6 +87,16 @@ "description": "Location of the log file. For instance, `/var/log`.", "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener" }, + { + "name": "logging.file.total-size-cap", + "type": "org.springframework.util.unit.DataSize", + "description": "Total size of log backups to be kept. Only supported with the default logback setup.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": "0B", + "deprecation": { + "replacement": "logging.logback.rollingpolicy.total-size-cap" + } + }, { "name": "logging.group", "type": "java.util.Map>", @@ -69,6 +109,46 @@ "description": "Log levels severity mapping. For instance, `logging.level.org.springframework=DEBUG`.", "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener" }, + { + "name": "logging.log4j2.config.override", + "type": "java.util.List", + "description": "Overriding configuration files used to create a composite configuration." + }, + { + "name": "logging.logback.rollingpolicy.clean-history-on-start", + "type": "java.lang.Boolean", + "description": "Whether to clean the archive log files on startup.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": false + }, + { + "name": "logging.logback.rollingpolicy.file-name-pattern", + "type": "java.lang.String", + "description": "Pattern for rolled-over log file names.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": "${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz" + }, + { + "name": "logging.logback.rollingpolicy.max-file-size", + "type": "org.springframework.util.unit.DataSize", + "description": "Maximum log file size.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": "10MB" + }, + { + "name": "logging.logback.rollingpolicy.max-history", + "type": "java.lang.Integer", + "description": "Maximum number of archive log files to keep.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": 7 + }, + { + "name": "logging.logback.rollingpolicy.total-size-cap", + "type": "org.springframework.util.unit.DataSize", + "description": "Total size of log backups to be kept.", + "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", + "defaultValue": "0B" + }, { "name": "logging.path", "type": "java.lang.String", @@ -106,13 +186,6 @@ "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", "defaultValue": "%5p" }, - { - "name": "logging.register-shutdown-hook", - "type": "java.lang.Boolean", - "description": "Register a shutdown hook for the logging system when it is initialized. Disabled automatically when deployed as a war file.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": true - }, { "name": "logging.pattern.rolling-file-name", "type": "java.lang.String", @@ -124,84 +197,11 @@ } }, { - "name": "logging.file.clean-history-on-start", - "type": "java.lang.Boolean", - "description": "Whether to clean the archive log files on startup. Only supported with the default logback setup.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": false, - "deprecation": { - "replacement": "logging.logback.rollingpolicy.clean-history-on-start" - } - }, - { - "name": "logging.file.max-size", - "type": "org.springframework.util.unit.DataSize", - "description": "Maximum log file size. Only supported with the default logback setup.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": "10MB", - "deprecation": { - "replacement": "logging.logback.rollingpolicy.max-file-size" - } - }, - { - "name": "logging.file.total-size-cap", - "type": "org.springframework.util.unit.DataSize", - "description": "Total size of log backups to be kept. Only supported with the default logback setup.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": "0B", - "deprecation": { - "replacement": "logging.logback.rollingpolicy.total-size-cap" - } - }, - { - "name": "logging.file.max-history", - "type": "java.lang.Integer", - "description": "Maximum number of archive log files to keep. Only supported with the default logback setup.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": 7, - "deprecation": { - "replacement": "logging.logback.rollingpolicy.max-history" - } - }, - { - "name": "logging.logback.rollingpolicy.file-name-pattern", - "type": "java.lang.String", - "description": "Pattern for rolled-over log file names.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": "${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz" - }, - { - "name": "logging.logback.rollingpolicy.clean-history-on-start", + "name": "logging.register-shutdown-hook", "type": "java.lang.Boolean", - "description": "Whether to clean the archive log files on startup.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": false - }, - { - "name": "logging.logback.rollingpolicy.max-file-size", - "type": "org.springframework.util.unit.DataSize", - "description": "Maximum log file size.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": "10MB" - }, - { - "name": "logging.logback.rollingpolicy.total-size-cap", - "type": "org.springframework.util.unit.DataSize", - "description": "Total size of log backups to be kept.", - "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": "0B" - }, - { - "name": "logging.logback.rollingpolicy.max-history", - "type": "java.lang.Integer", - "description": "Maximum number of archive log files to keep.", + "description": "Register a shutdown hook for the logging system when it is initialized. Disabled automatically when deployed as a war file.", "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener", - "defaultValue": 7 - }, - { - "name": "logging.log4j2.config.override", - "type": "java.util.List", - "description": "Overriding configuration files used to create a composite configuration." + "defaultValue": true }, { "name": "spring.application.index", @@ -929,18 +929,18 @@ "description": "Name of the profile to enable if no profile is active.", "defaultValue": "default" }, - { - "name": "spring.profiles.include", - "type": "java.util.List", - "sourceType": "org.springframework.boot.context.config.Profiles", - "description": "Unconditionally activate the specified comma-separated list of profiles (or list of profiles if using YAML)." - }, { "name": "spring.profiles.group", "type": "java.util.Map>", "sourceType": "org.springframework.boot.context.config.Profiles", "description": "Profile groups to define a logical name for a related group of profiles." }, + { + "name": "spring.profiles.include", + "type": "java.util.List", + "sourceType": "org.springframework.boot.context.config.Profiles", + "description": "Unconditionally activate the specified comma-separated list of profiles (or list of profiles if using YAML)." + }, { "name": "spring.reactor.debug-agent.enabled", "type": "java.lang.Boolean", @@ -1021,22 +1021,6 @@ } ] }, - { - "name": "spring.profiles.active", - "providers": [ - { - "name": "spring-profile-name" - } - ] - }, - { - "name": "spring.profiles.include", - "providers": [ - { - "name": "spring-profile-name" - } - ] - }, { "name": "spring.config.import", "values": [ @@ -1055,6 +1039,22 @@ "name": "any" } ] + }, + { + "name": "spring.profiles.active", + "providers": [ + { + "name": "spring-profile-name" + } + ] + }, + { + "name": "spring.profiles.include", + "providers": [ + { + "name": "spring-profile-name" + } + ] } ] } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java index 6a26e696a3f6..63a006cab0d8 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanTests.java @@ -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. @@ -222,6 +222,32 @@ void forValueObjectWithConstructorBindingAnnotatedClassReturnsBean() { .getBindConstructor(ConstructorBindingOnConstructor.class, false)).isNotNull(); } + @Test + @EnabledForJreRange(min = JRE.JAVA_16) + void forValueObjectWithConstructorBindingAnnotatedRecordReturnsBean() { + Class constructorBindingRecord = new ByteBuddy(ClassFileVersion.JAVA_V16).makeRecord() + .name("org.springframework.boot.context.properties.RecordProperties") + .annotateType(AnnotationDescription.Builder.ofType(ConfigurationProperties.class) + .define("prefix", "explicit").build()) + .annotateType(AnnotationDescription.Builder.ofType(ConstructorBinding.class).build()) + .defineRecordComponent("someString", String.class).defineRecordComponent("someInteger", Integer.class) + .make().load(getClass().getClassLoader()).getLoaded(); + ConfigurationPropertiesBean propertiesBean = ConfigurationPropertiesBean + .forValueObject(constructorBindingRecord, "constructorBindingRecord"); + assertThat(propertiesBean.getName()).isEqualTo("constructorBindingRecord"); + assertThat(propertiesBean.getInstance()).isNull(); + assertThat(propertiesBean.getType()).isEqualTo(constructorBindingRecord); + assertThat(propertiesBean.getBindMethod()).isEqualTo(BindMethod.VALUE_OBJECT); + assertThat(propertiesBean.getAnnotation()).isNotNull(); + Bindable target = propertiesBean.asBindTarget(); + assertThat(target.getType()).isEqualTo(ResolvableType.forClass(constructorBindingRecord)); + assertThat(target.getValue()).isNull(); + Constructor bindConstructor = ConfigurationPropertiesBindConstructorProvider.INSTANCE + .getBindConstructor(constructorBindingRecord, false); + assertThat(bindConstructor).isNotNull(); + assertThat(bindConstructor.getParameterTypes()).containsExactly(String.class, Integer.class); + } + @Test @EnabledForJreRange(min = JRE.JAVA_16) void forValueObjectWithUnannotatedRecordReturnsBean() { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/ValueObjectBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/ValueObjectBinderTests.java index 7286c7c348ec..82cb5e89f8d0 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/ValueObjectBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/ValueObjectBinderTests.java @@ -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. @@ -16,23 +16,35 @@ package org.springframework.boot.context.properties.bind; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; import java.lang.reflect.Constructor; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; +import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.MockConfigurationPropertySource; +import org.springframework.boot.testsupport.compiler.TestCompiler; import org.springframework.core.ResolvableType; import org.springframework.core.convert.ConversionService; import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.Assert; import static org.assertj.core.api.Assertions.assertThat; @@ -357,6 +369,30 @@ void bindToAnnotationNamedParameter() { assertThat(bound.getImportName()).isEqualTo("test"); } + @Test + @EnabledForJreRange(min = JRE.JAVA_16) + void bindToRecordWithDefaultValue(@TempDir File tempDir) throws IOException, ClassNotFoundException { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("test.record.property1", "value-from-config-1"); + this.sources.add(source); + File recordProperties = new File(tempDir, "RecordProperties.java"); + try (PrintWriter writer = new PrintWriter(new FileWriter(recordProperties))) { + writer.println("public record RecordProperties("); + writer.println( + "@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-1\") String property1,"); + writer.println( + "@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-2\") String property2"); + writer.println(") {"); + writer.println("}"); + } + TestCompiler compiler = new TestCompiler(tempDir); + compiler.getTask(Arrays.asList(recordProperties)).call(); + ClassLoader ucl = new URLClassLoader(new URL[] { tempDir.toURI().toURL() }); + Object bean = this.binder.bind("test.record", Class.forName("RecordProperties", true, ucl)).get(); + assertThat(ReflectionTestUtils.getField(bean, "property1")).isEqualTo("value-from-config-1"); + assertThat(ReflectionTestUtils.getField(bean, "property2")).isEqualTo("default-value-2"); + } + private void noConfigurationProperty(BindException ex) { assertThat(ex.getProperty()).isNull(); } diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/java/org/springframework/boot/loader/LoaderIntegrationTests.java b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/java/org/springframework/boot/loader/LoaderIntegrationTests.java index 5162ea39677c..8aa27b2efdcd 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/java/org/springframework/boot/loader/LoaderIntegrationTests.java +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/java/org/springframework/boot/loader/LoaderIntegrationTests.java @@ -23,8 +23,6 @@ import java.util.function.Supplier; import java.util.stream.Stream; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.testcontainers.containers.GenericContainer; @@ -52,7 +50,6 @@ class LoaderIntegrationTests { @ParameterizedTest @MethodSource("javaRuntimes") - @EnabledForJreRange(max = JRE.JAVA_17) void readUrlsWithoutWarning(JavaRuntime javaRuntime) { try (GenericContainer container = createContainer(javaRuntime)) { container.start(); @@ -81,6 +78,7 @@ static Stream javaRuntimes() { javaRuntimes.add(JavaRuntime.openJdk(JavaVersion.EIGHT)); javaRuntimes.add(JavaRuntime.openJdk(JavaVersion.ELEVEN)); javaRuntimes.add(JavaRuntime.openJdk(JavaVersion.SEVENTEEN)); + javaRuntimes.add(JavaRuntime.openJdk(JavaVersion.EIGHTEEN)); javaRuntimes.add(JavaRuntime.oracleJdk17()); return javaRuntimes.stream().filter(JavaRuntime::isCompatible); } diff --git a/src/checkstyle/checkstyle.xml b/src/checkstyle/checkstyle.xml index 148febe43fcc..90f953dfc567 100644 --- a/src/checkstyle/checkstyle.xml +++ b/src/checkstyle/checkstyle.xml @@ -13,7 +13,7 @@ name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck"> + value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|logging|pool2).*, ^com\.datastax\.oss\.driver\.shaded.*, ^com\.google\.common.*, ^io\.micrometer\.shaded.*, ^org\.flywaydb\.core\.internal.*, ^org\.jetbrains\.annotations.*, ^org\.testcontainers\.shaded.*" /> diff --git a/src/checkstyle/import-control.xml b/src/checkstyle/import-control.xml index af145b76d5c5..445d18591cb0 100644 --- a/src/checkstyle/import-control.xml +++ b/src/checkstyle/import-control.xml @@ -2,6 +2,7 @@ + @@ -45,6 +46,13 @@ + + + + + + + @@ -56,6 +64,9 @@ + + +