From bf010b65323adf22fcc6690d408580a5d5b8bb73 Mon Sep 17 00:00:00 2001 From: Spring Builds Date: Fri, 19 Jan 2024 07:01:14 +0000 Subject: [PATCH 001/182] Next development version (v3.2.3-SNAPSHOT) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d6dd96dafc1a..22d7baf4a925 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=3.2.2-SNAPSHOT +version=3.2.3-SNAPSHOT org.gradle.caching=true org.gradle.parallel=true From 302087176af760a2ffa408217bda3c5f5e2e3e37 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Fri, 19 Jan 2024 17:29:12 -0600 Subject: [PATCH 002/182] Upgrade to Java 17.0.10+13 Closes gh-39216 --- .sdkmanrc | 2 +- ci/images/get-jdk-url.sh | 2 +- .../spring-boot-launch-script-tests/build.gradle | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.sdkmanrc b/.sdkmanrc index 6dbcaa9337a9..c217333df42a 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1,3 +1,3 @@ # Enable auto-env through the sdkman_auto_env config # Add key=value pairs of SDKs to use below -java=17.0.9-librca +java=17.0.10-librca diff --git a/ci/images/get-jdk-url.sh b/ci/images/get-jdk-url.sh index f026e7fea70e..cf0495c6e60f 100755 --- a/ci/images/get-jdk-url.sh +++ b/ci/images/get-jdk-url.sh @@ -3,7 +3,7 @@ set -e case "$1" in java17) - echo "https://github.com/bell-sw/Liberica/releases/download/17.0.9+11/bellsoft-jdk17.0.9+11-linux-amd64.tar.gz" + echo "https://github.com/bell-sw/Liberica/releases/download/17.0.10+13/bellsoft-jdk17.0.10+13-linux-amd64.tar.gz" ;; java21) echo "https://github.com/bell-sw/Liberica/releases/download/21.0.2+14/bellsoft-jdk21.0.2+14-linux-amd64.tar.gz" diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/build.gradle b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/build.gradle index 7b39a164bf39..db4e6b461290 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/build.gradle +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/build.gradle @@ -7,7 +7,7 @@ plugins { description = "Spring Boot Launch Script Integration Tests" -def jdkVersion = "17.0.8.1+1" +def jdkVersion = "17.0.10+13" def jdkArch = "aarch64".equalsIgnoreCase(System.getProperty("os.arch")) ? "aarch64" : "amd64" configurations { From 9c87a7e4ed42e2985e1fe503385ea6ab8ea873eb Mon Sep 17 00:00:00 2001 From: Eric Haag Date: Thu, 18 Jan 2024 15:16:59 -0600 Subject: [PATCH 003/182] Update Revved up by Develocity badge See gh-39242 --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index b0e635135a51..15a75140de89 100755 --- a/README.adoc +++ b/README.adoc @@ -1,4 +1,4 @@ -= Spring Boot image:https://ci.spring.io/api/v1/teams/spring-boot/pipelines/spring-boot-3.1.x/jobs/build/badge["Build Status", link="https://ci.spring.io/teams/spring-boot/pipelines/spring-boot-3.1.x?groups=Build"] image:https://badges.gitter.im/Join Chat.svg["Chat",link="https://gitter.im/spring-projects/spring-boot?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image:https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Gradle Enterprise", link="https://ge.spring.io/scans?&search.rootProjectNames=Spring%20Boot%20Build&search.rootProjectNames=spring-boot-build"] += Spring Boot image:https://ci.spring.io/api/v1/teams/spring-boot/pipelines/spring-boot-3.1.x/jobs/build/badge["Build Status", link="https://ci.spring.io/teams/spring-boot/pipelines/spring-boot-3.1.x?groups=Build"] image:https://badges.gitter.im/Join Chat.svg["Chat",link="https://gitter.im/spring-projects/spring-boot?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image:https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A["Revved up by Develocity", link="https://ge.spring.io/scans?&search.rootProjectNames=Spring%20Boot%20Build&search.rootProjectNames=spring-boot-build"] :docs: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference :github: https://github.com/spring-projects/spring-boot From 16c0f035a90e67d5145b99ea34038f37ade0944f Mon Sep 17 00:00:00 2001 From: Vaibhav Jaiswal Date: Mon, 22 Jan 2024 18:11:28 +0530 Subject: [PATCH 004/182] Make PropagationType a public type The PropagationType enum is returned from public methods so should be public itself. See gh-39265 --- .../boot/actuate/autoconfigure/tracing/TracingProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java index 6f598cc41b95..7bbff40574b5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java @@ -224,7 +224,7 @@ List getEffectiveConsumedTypes() { /** * Supported propagation types. The declared order of the values matter. */ - enum PropagationType { + public enum PropagationType { /** * W3C propagation. From 87ea2b75fb14ed5c69f8a9677f75fc367e2ec3e6 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 22 Jan 2024 11:49:45 -0800 Subject: [PATCH 005/182] Polish 'Make PropagationType a public type' See gh-39265 --- .../boot/actuate/autoconfigure/tracing/TracingProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java index 7bbff40574b5..c38ef94d1253 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/TracingProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. From e1986ea11eeb5b8892b91dcb62dc41cc57fa4d18 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 22 Jan 2024 12:20:06 -0800 Subject: [PATCH 006/182] Update copyright year of changed files --- .../boot/autoconfigure/amqp/RabbitProperties.java | 2 +- .../testresttemplate/MySpringBootTestsConfiguration.java | 2 +- .../boot/diagnostics/analyzer/PatternParseFailureAnalyzer.java | 2 +- .../diagnostics/analyzer/PatternParseFailureAnalyzerTests.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java index 02524e256024..53e88d0ac741 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java index 13625a03569c..b9de7e86c5b7 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/utilities/testresttemplate/MySpringBootTestsConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzer.java index a9eae1eb2268..5b779d96897a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzerTests.java index 87eb14b67d2d..07d8bff36942 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/PatternParseFailureAnalyzerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. From c87d5eeb28cac4071771251680b7b614194a62f6 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 23 Jan 2024 08:53:06 +0100 Subject: [PATCH 007/182] Ensure that remaining mocks are closed before initializing a test Closes gh-39271 --- .../mockito/MockitoTestExecutionListener.java | 18 +++-- ...TestExecutionListenerIntegrationTests.java | 71 +++++++++++++++++++ 2 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java index 45712061c92c..975d916b744d 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java @@ -43,6 +43,7 @@ * * @author Phillip Webb * @author Andy Wilkinson + * @author Moritz Halbritter * @since 1.4.2 * @see ResetMocksTestExecutionListener */ @@ -57,12 +58,13 @@ public final int getOrder() { @Override public void prepareTestInstance(TestContext testContext) throws Exception { + closeMocks(testContext); initMocks(testContext); injectFields(testContext); } @Override - public void beforeTestMethod(TestContext testContext) throws Exception { + public void beforeTestMethod(TestContext testContext) { if (Boolean.TRUE.equals( testContext.getAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE))) { initMocks(testContext); @@ -72,10 +74,7 @@ public void beforeTestMethod(TestContext testContext) throws Exception { @Override public void afterTestMethod(TestContext testContext) throws Exception { - Object mocks = testContext.getAttribute(MOCKS_ATTRIBUTE_NAME); - if (mocks instanceof AutoCloseable closeable) { - closeable.close(); - } + closeMocks(testContext); } private void initMocks(TestContext testContext) { @@ -84,6 +83,13 @@ private void initMocks(TestContext testContext) { } } + private void closeMocks(TestContext testContext) throws Exception { + Object mocks = testContext.getAttribute(MOCKS_ATTRIBUTE_NAME); + if (mocks instanceof AutoCloseable closeable) { + closeable.close(); + } + } + private boolean hasMockitoAnnotations(TestContext testContext) { MockitoAnnotationCollection collector = new MockitoAnnotationCollection(); ReflectionUtils.doWithFields(testContext.getTestClass(), collector); @@ -126,7 +132,7 @@ private static final class MockitoAnnotationCollection implements FieldCallback private final Set annotations = new LinkedHashSet<>(); @Override - public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { + public void doWith(Field field) throws IllegalArgumentException { for (Annotation annotation : field.getDeclaredAnnotations()) { if (annotation.annotationType().getName().startsWith("org.mockito")) { this.annotations.add(annotation); diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java new file mode 100644 index 000000000000..4de401b078a2 --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2024 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.test.mock.mockito; + +import java.util.UUID; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; + +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link MockitoTestExecutionListener}. + * + * @author Moritz Halbritter + */ +@ExtendWith(SpringExtension.class) +class MockitoTestExecutionListenerIntegrationTests { + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + class DisabledTests { + + private static final UUID uuid = UUID.randomUUID(); + + @Mock + private MockedStatic mockedStatic; + + @Test + @Order(1) + @Disabled + void shouldReturnConstantValueDisabled() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + @Test + @Order(2) + void shouldReturnConstantValue() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + } + +} From b245283b29ebfc4080a5c41bd045c3931d5198ff Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 23 Jan 2024 09:29:37 +0100 Subject: [PATCH 008/182] Add .git-hooks to the git ignore list When following https://github.com/spring-projects/spring-boot/wiki/Working-with-Git-branches, a new directory named .git-hooks is created when using git worktree support. This directory should be on the ignore list. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a5256ecef4fa..2a812bc5079c 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ target secrets.yml .gradletasknamecache .sts4-cache +.git-hooks/ From c99daf5de4f51214f6bca55e636e61b3379eb99a Mon Sep 17 00:00:00 2001 From: Jan Engehausen Date: Tue, 23 Jan 2024 16:49:24 +0100 Subject: [PATCH 009/182] Fix typo 'Unuthorized' See gh-39279 --- .../spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc index 4787fd22214a..0d5a036e94ed 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/endpoints.adoc @@ -301,7 +301,7 @@ By default, any authenticated user is authorized. For JMX endpoints, all users are always authorized. The following example allows all users with the `admin` role to view values from the `/env` endpoint in their original form. -Unuthorized users, or users without the `admin` role, will see only sanitized values. +Unauthorized users, or users without the `admin` role, will see only sanitized values. [source,yaml,indent=0,subs="verbatim",configprops,configblocks] ---- From d702c2f8606ad7f0881b6586179c000ecd8bd89e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 24 Jan 2024 13:59:43 +0000 Subject: [PATCH 010/182] Permit upgrades to Jetty Reactive HTTPClient 4.0.2 Closes gh-39288 --- spring-boot-project/spring-boot-dependencies/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 63c2c287ab98..37e4674049e8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -672,10 +672,6 @@ bom { } } library("Jetty Reactive HTTPClient", "4.0.1") { - prohibit { - versionRange "[4.0.2]" - because "it causes problems in Spring Framework (https://github.com/spring-projects/spring-framework/issues/31931#issue-2061468092)" - } group("org.eclipse.jetty") { modules = [ "jetty-reactive-httpclient" From ac0d95beb4bfacef5e32284317277045afac6999 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 24 Jan 2024 14:19:27 -0600 Subject: [PATCH 011/182] Upgrade CI to Docker 25.0.1 Closes gh-39292 --- ci/images/get-docker-url.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/images/get-docker-url.sh b/ci/images/get-docker-url.sh index 965d738b72cb..1e4971b85383 100755 --- a/ci/images/get-docker-url.sh +++ b/ci/images/get-docker-url.sh @@ -1,5 +1,5 @@ #!/bin/bash set -e -version="24.0.7" +version="25.0.1" echo "https://download.docker.com/linux/static/stable/x86_64/docker-$version.tgz"; From 930669888a3d320fff39b491a22aa569ccef0fab Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Thu, 25 Jan 2024 10:18:03 +0100 Subject: [PATCH 012/182] Add more integration tests for MockitoTestExecutionListener --- ...TestExecutionListenerIntegrationTests.java | 312 +++++++++++++++++- 1 file changed, 310 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java index 4de401b078a2..7dbe1367005d 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java @@ -16,21 +16,30 @@ package org.springframework.boot.test.mock.mockito; +import java.util.List; import java.util.UUID; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.MockedStatic; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; /** * Integration tests for {@link MockitoTestExecutionListener}. @@ -42,7 +51,7 @@ class MockitoTestExecutionListenerIntegrationTests { @Nested @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class DisabledTests { + class MockedStaticTests { private static final UUID uuid = UUID.randomUUID(); @@ -60,7 +69,7 @@ void shouldReturnConstantValueDisabled() { @Test @Order(2) - void shouldReturnConstantValue() { + void shouldNotFailBecauseOfMockedStaticNotBeingClosed() { this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); UUID result = UUID.randomUUID(); assertThat(result).isEqualTo(uuid); @@ -68,4 +77,303 @@ void shouldReturnConstantValue() { } + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + class ConfigureMockInBeforeEach { + + @Mock + private List mock; + + @BeforeEach + void setUp() { + given(this.mock.size()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.size()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.size()).willReturn(2); + assertThat(this.mock.size()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotBeAffectedByOtherTests() { + assertThat(this.mock.size()).isEqualTo(1); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestInstance(Lifecycle.PER_CLASS) + class ConfigureMockInBeforeAll { + + @Mock + private List mock; + + @BeforeAll + void setUp() { + given(this.mock.size()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.size()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.size()).willReturn(2); + assertThat(this.mock.size()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotBeAffectedByOtherTest() { + assertThat(this.mock.size()).isEqualTo(2); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetAfterInBeforeEach { + + @MockBean(reset = MockReset.AFTER) + private MyBean mock; + + @BeforeEach + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.call()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotBeAffectedByOtherTests() { + assertThat(this.mock.call()).isEqualTo(1); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetBeforeInBeforeEach { + + @MockBean(reset = MockReset.BEFORE) + private MyBean mock; + + @BeforeEach + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.call()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotBeAffectedByOtherTests() { + assertThat(this.mock.call()).isEqualTo(1); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetNoneInBeforeEach { + + @MockBean(reset = MockReset.NONE) + private MyBean mock; + + @BeforeEach + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.call()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotBeAffectedByOtherTests() { + assertThat(this.mock.call()).isEqualTo(1); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestInstance(Lifecycle.PER_CLASS) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetAfterInBeforeAll { + + @MockBean(reset = MockReset.AFTER) + private MyBean mock; + + @BeforeAll + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.call()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldResetMockAfterReconfiguration() { + assertThat(this.mock.call()).isEqualTo(0); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestInstance(Lifecycle.PER_CLASS) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetBeforeInBeforeAll { + + @MockBean(reset = MockReset.BEFORE) + private MyBean mock; + + @BeforeAll + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldResetMockBeforeThisMethod() { + assertThat(this.mock.call()).isEqualTo(0); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldResetMockAfterReconfiguration() { + assertThat(this.mock.call()).isEqualTo(0); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestInstance(Lifecycle.PER_CLASS) + @Import(MyBeanConfiguration.class) + class ConfigureMockBeanWithResetNoneInBeforeAll { + + @MockBean(reset = MockReset.NONE) + private MyBean mock; + + @BeforeAll + void setUp() { + given(this.mock.call()).willReturn(1); + } + + @Test + @Order(1) + void shouldUseSetUpConfiguration() { + assertThat(this.mock.call()).isEqualTo(1); + } + + @Test + @Order(2) + void shouldBeAbleToReconfigureMock() { + given(this.mock.call()).willReturn(2); + assertThat(this.mock.call()).isEqualTo(2); + } + + @Test + @Order(3) + void shouldNotResetMock() { + assertThat(this.mock.call()).isEqualTo(2); + } + + } + + interface MyBean { + + int call(); + + } + + private static final class DefaultMyBean implements MyBean { + + @Override + public int call() { + return -1; + } + + } + + @TestConfiguration(proxyBeanMethods = false) + private static final class MyBeanConfiguration { + + @Bean + MyBean myBean() { + return new DefaultMyBean(); + } + + } + } From df755db1f36ad6b61de9ffef7aff359b66415e02 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Thu, 25 Jan 2024 10:57:45 +0100 Subject: [PATCH 013/182] Ensure that remaining mocks are closed before initializing a test Closes gh-39271 --- .../mockito/MockitoTestExecutionListener.java | 8 +- ...TestExecutionListenerIntegrationTests.java | 120 ++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java index 975d916b744d..be4561d45a53 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java @@ -64,9 +64,10 @@ public void prepareTestInstance(TestContext testContext) throws Exception { } @Override - public void beforeTestMethod(TestContext testContext) { + public void beforeTestMethod(TestContext testContext) throws Exception { if (Boolean.TRUE.equals( testContext.getAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE))) { + closeMocks(testContext); initMocks(testContext); reinjectFields(testContext); } @@ -77,6 +78,11 @@ public void afterTestMethod(TestContext testContext) throws Exception { closeMocks(testContext); } + @Override + public void afterTestClass(TestContext testContext) throws Exception { + closeMocks(testContext); + } + private void initMocks(TestContext testContext) { if (hasMockitoAnnotations(testContext)) { testContext.setAttribute(MOCKS_ATTRIBUTE_NAME, MockitoAnnotations.openMocks(testContext.getTestInstance())); diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java index 7dbe1367005d..1357629a616d 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerIntegrationTests.java @@ -21,11 +21,13 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestClassOrder; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.TestMethodOrder; @@ -36,6 +38,8 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.assertj.core.api.Assertions.assertThat; @@ -77,6 +81,122 @@ void shouldNotFailBecauseOfMockedStaticNotBeingClosed() { } + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD) + class MockedStaticTestsDirtiesContext { + + private static final UUID uuid = UUID.randomUUID(); + + @Mock + private MockedStatic mockedStatic; + + @Test + @Order(1) + @Disabled + void shouldReturnConstantValueDisabled() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + @Test + @Order(2) + void shouldNotFailBecauseOfMockedStaticNotBeingClosed() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + @Test + @Order(3) + void shouldNotFailBecauseOfMockedStaticNotBeingClosedWhenMocksAreReinjected() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestClassOrder(ClassOrderer.OrderAnnotation.class) + class MockedStaticTestsIfClassContainsOnlyDisabledTests { + + @Nested + @Order(1) + class TestClass1 { + + private static final UUID uuid = UUID.randomUUID(); + + @Mock + private MockedStatic mockedStatic; + + @Test + @Order(1) + @Disabled + void disabledTest() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + } + + } + + @Nested + @Order(2) + class TestClass2 { + + private static final UUID uuid = UUID.randomUUID(); + + @Mock + private MockedStatic mockedStatic; + + @Test + @Order(1) + void shouldNotFailBecauseMockedStaticHasNotBeenClosed() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + } + + } + + @Nested + @TestMethodOrder(MethodOrderer.OrderAnnotation.class) + @TestClassOrder(ClassOrderer.OrderAnnotation.class) + class MockedStaticTestsIfClassContainsNoTests { + + @Nested + @Order(1) + class TestClass1 { + + @Mock + private MockedStatic mockedStatic; + + } + + @Nested + @Order(2) + class TestClass2 { + + private static final UUID uuid = UUID.randomUUID(); + + @Mock + private MockedStatic mockedStatic; + + @Test + @Order(1) + void shouldNotFailBecauseMockedStaticHasNotBeenClosed() { + this.mockedStatic.when(UUID::randomUUID).thenReturn(uuid); + UUID result = UUID.randomUUID(); + assertThat(result).isEqualTo(uuid); + } + + } + + } + @Nested @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class ConfigureMockInBeforeEach { From a6d1788be3e5613b033a20b6f64560b04efd6b61 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 25 Jan 2024 11:14:45 +0000 Subject: [PATCH 014/182] Tolerate OS and Java version differences in ExtractCommandTests Co-Authored-By: Moritz Halbritter Closes gh-39303 --- .../layertools/ExtractCommandTests.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/java/org/springframework/boot/jarmode/layertools/ExtractCommandTests.java b/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/java/org/springframework/boot/jarmode/layertools/ExtractCommandTests.java index 1ec5a39214bf..c2d2a815dcb3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/java/org/springframework/boot/jarmode/layertools/ExtractCommandTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-jarmode-layertools/src/test/java/org/springframework/boot/jarmode/layertools/ExtractCommandTests.java @@ -21,6 +21,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.Runtime.Version; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.attribute.BasicFileAttributeView; @@ -30,6 +31,7 @@ import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.Iterator; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -38,6 +40,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.JRE; +import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.mockito.Mock; @@ -59,11 +63,13 @@ @ExtendWith(MockitoExtension.class) class ExtractCommandTests { - private static final FileTime CREATION_TIME = FileTime.from(Instant.now().minus(3, ChronoUnit.DAYS)); + private static final Instant NOW = Instant.now(); - private static final FileTime LAST_MODIFIED_TIME = FileTime.from(Instant.now().minus(2, ChronoUnit.DAYS)); + private static final FileTime CREATION_TIME = FileTime.from(NOW.minus(3, ChronoUnit.DAYS)); - private static final FileTime LAST_ACCESS_TIME = FileTime.from(Instant.now().minus(1, ChronoUnit.DAYS)); + private static final FileTime LAST_MODIFIED_TIME = FileTime.from(NOW.minus(2, ChronoUnit.DAYS)); + + private static final FileTime LAST_ACCESS_TIME = FileTime.from(NOW.minus(1, ChronoUnit.DAYS)); @TempDir File temp; @@ -107,10 +113,11 @@ private void timeAttributes(File file) { .readAttributes(); assertThat(basicAttributes.lastModifiedTime().to(TimeUnit.SECONDS)) .isEqualTo(LAST_MODIFIED_TIME.to(TimeUnit.SECONDS)); - assertThat(basicAttributes.creationTime().to(TimeUnit.SECONDS)).satisfiesAnyOf( - (creationTime) -> assertThat(creationTime).isEqualTo(CREATION_TIME.to(TimeUnit.SECONDS)), - // On macOS (at least) the creation time is the last modified time - (creationTime) -> assertThat(creationTime).isEqualTo(LAST_MODIFIED_TIME.to(TimeUnit.SECONDS))); + FileTime expectedCreationTime = expectedCreationTime(); + if (expectedCreationTime != null) { + assertThat(basicAttributes.creationTime().to(TimeUnit.SECONDS)) + .isEqualTo(expectedCreationTime.to(TimeUnit.SECONDS)); + } assertThat(basicAttributes.lastAccessTime().to(TimeUnit.SECONDS)) .isEqualTo(LAST_ACCESS_TIME.to(TimeUnit.SECONDS)); } @@ -119,6 +126,22 @@ private void timeAttributes(File file) { } } + private FileTime expectedCreationTime() { + // macOS uses last modified time until Java 20 where it uses creation time. + // https://github.com/openjdk/jdk21u-dev/commit/6397d564a5dab07f81bf4c69b116ebfabb2446ba + if (OS.MAC.isCurrentOs()) { + return (EnumSet.range(JRE.JAVA_17, JRE.JAVA_19).contains(JRE.currentVersion())) ? LAST_MODIFIED_TIME + : CREATION_TIME; + } + if (OS.LINUX.isCurrentOs()) { + // Linux uses the modified time until Java 21.0.2 where a bug means that it + // uses the birth time which it has not set, preventing us from verifying it. + // https://github.com/openjdk/jdk21u-dev/commit/4cf572e3b99b675418e456e7815fb6fd79245e30 + return (Runtime.version().compareTo(Version.parse("21.0.2")) >= 0) ? null : LAST_MODIFIED_TIME; + } + return CREATION_TIME; + } + @Test void runWhenHasDestinationOptionExtractsLayers() { given(this.context.getArchiveFile()).willReturn(this.jarFile); From 1247f8920923c7c0a173516de3a192a962951a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Thu, 25 Jan 2024 17:22:19 -0500 Subject: [PATCH 015/182] Polish See gh-39312 --- .../ActiveMQDockerComposeConnectionDetailsFactory.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/activemq/ActiveMQDockerComposeConnectionDetailsFactory.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/activemq/ActiveMQDockerComposeConnectionDetailsFactory.java index ac3809d8da21..30597c45a8dd 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/activemq/ActiveMQDockerComposeConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/activemq/ActiveMQDockerComposeConnectionDetailsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.docker.compose.service.connection.activemq; -import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails; import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails; import org.springframework.boot.docker.compose.core.RunningService; import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; @@ -43,7 +42,7 @@ protected ActiveMQConnectionDetails getDockerComposeConnectionDetails(DockerComp } /** - * {@link RabbitConnectionDetails} backed by a {@code rabbitmq} + * {@link ActiveMQConnectionDetails} backed by a {@code activemq} * {@link RunningService}. */ static class ActiveMQDockerComposeConnectionDetails extends DockerComposeConnectionDetails From 6eaabaa433cddcf0fee3029494f2d6d6fa6a48f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 19:30:29 +0000 Subject: [PATCH 016/182] Bump gradle/gradle-build-action from 2.11.1 to 2.12.0 Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2.11.1 to 2.12.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/982da8e78c05368c70dac0351bb82647a9e9a5d2...a8f75513eafdebd8141bd1cd4e30fcd194af8dfa) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] See gh-39329 --- .github/workflows/build-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 37205707ea20..94f00d2050f3 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -23,7 +23,7 @@ jobs: uses: gradle/wrapper-validation-action@v1 - name: Set up Gradle - uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa - name: Build env: From a85e99790b3f02b8b60180e9b3935901bf01045d Mon Sep 17 00:00:00 2001 From: Piyal Ahmed Date: Wed, 24 Jan 2024 16:34:16 +0600 Subject: [PATCH 017/182] Fix NestedJarFile constructor javadoc See gh-39285 --- .../boot/loader/jar/NestedJarFile.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/NestedJarFile.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/NestedJarFile.java index 1c2fea69a403..6168202950ea 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/NestedJarFile.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/NestedJarFile.java @@ -101,8 +101,10 @@ public class NestedJarFile extends JarFile { * Creates a new {@link NestedJarFile} instance to read from the specific * {@code File}. * @param file the jar file to be opened for reading - * @param nestedEntryName the nested entry name to open or {@code null} + * @param nestedEntryName the nested entry name to open * @throws IOException on I/O error + * @throws IllegalArgumentException if {@code nestedEntryName} is {@code null} or + * empty */ public NestedJarFile(File file, String nestedEntryName) throws IOException { this(file, nestedEntryName, null, true, Cleaner.instance); @@ -112,9 +114,11 @@ public NestedJarFile(File file, String nestedEntryName) throws IOException { * Creates a new {@link NestedJarFile} instance to read from the specific * {@code File}. * @param file the jar file to be opened for reading - * @param nestedEntryName the nested entry name to open or {@code null} + * @param nestedEntryName the nested entry name to open * @param version the release version to use when opening a multi-release jar * @throws IOException on I/O error + * @throws IllegalArgumentException if {@code nestedEntryName} is {@code null} or + * empty */ public NestedJarFile(File file, String nestedEntryName, Runtime.Version version) throws IOException { this(file, nestedEntryName, version, true, Cleaner.instance); @@ -124,11 +128,13 @@ public NestedJarFile(File file, String nestedEntryName, Runtime.Version version) * Creates a new {@link NestedJarFile} instance to read from the specific * {@code File}. * @param file the jar file to be opened for reading - * @param nestedEntryName the nested entry name to open or {@code null} + * @param nestedEntryName the nested entry name to open * @param version the release version to use when opening a multi-release jar * @param onlyNestedJars if only nested jars should be opened * @param cleaner the cleaner used to release resources * @throws IOException on I/O error + * @throws IllegalArgumentException if {@code nestedEntryName} is {@code null} or + * empty */ NestedJarFile(File file, String nestedEntryName, Runtime.Version version, boolean onlyNestedJars, Cleaner cleaner) throws IOException { From 1c2a622f7fcef9ebd5cb74ade3869a3dfc3ca6af Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 30 Jan 2024 11:56:26 +0000 Subject: [PATCH 018/182] Upgrade to Commons Compress 1.25.0 Closes gh-39148 --- spring-boot-project/spring-boot-parent/build.gradle | 2 +- .../spring-boot-buildpack-platform/build.gradle | 2 +- .../buildpack/platform/build/ImageBuildpack.java | 6 +++--- .../buildpack/platform/build/TarGzipBuildpack.java | 6 +++--- .../boot/buildpack/platform/docker/DockerApi.java | 4 ++-- .../platform/build/DirectoryBuildpackTests.java | 6 +++--- .../platform/build/ImageBuildpackTests.java | 6 +++--- .../buildpack/platform/docker/DockerApiTests.java | 10 +++++----- .../platform/docker/type/ImageArchiveTests.java | 12 ++++++------ .../buildpack/platform/docker/type/LayerTests.java | 8 ++++---- .../boot/buildpack/platform/io/TarArchiveTests.java | 6 +++--- .../buildpack/platform/io/TarLayoutWriterTests.java | 6 +++--- .../platform/io/ZipFileTarArchiveTests.java | 6 +++--- .../ApplicationPluginActionIntegrationTests.java | 6 +++--- .../boot/image/assertions/ImageAssert.java | 10 +++++----- 15 files changed, 48 insertions(+), 48 deletions(-) diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 48b8d88b3b6f..cf30f9dd5871 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -34,7 +34,7 @@ bom { ] } } - library("Commons Compress", "1.21") { + library("Commons Compress", "1.25.0") { group("org.apache.commons") { modules = [ "commons-compress" diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle index d890be6a2af9..d6b393c6819e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle @@ -22,7 +22,7 @@ dependencies { api("com.fasterxml.jackson.core:jackson-databind") api("com.fasterxml.jackson.module:jackson-module-parameter-names") api("net.java.dev.jna:jna-platform") - api("org.apache.commons:commons-compress:1.19") + api("org.apache.commons:commons-compress") api("org.apache.httpcomponents.client5:httpclient5") api("org.springframework:spring-core") api("org.tomlj:tomlj:1.0.0") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java index 5a76b8ab0cc2..827f4a8da015 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -131,12 +131,12 @@ private void copyLayerTar(Path path, OutputStream out) throws IOException { try (TarArchiveInputStream tarIn = new TarArchiveInputStream(Files.newInputStream(path)); TarArchiveOutputStream tarOut = new TarArchiveOutputStream(out)) { tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); - TarArchiveEntry entry = tarIn.getNextTarEntry(); + TarArchiveEntry entry = tarIn.getNextEntry(); while (entry != null) { tarOut.putArchiveEntry(entry); StreamUtils.copy(tarIn, tarOut); tarOut.closeArchiveEntry(); - entry = tarIn.getNextTarEntry(); + entry = tarIn.getNextEntry(); } tarOut.finish(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java index 735c76619f6a..4174166f3d27 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. @@ -90,13 +90,13 @@ private void copyAndRebaseEntries(OutputStream outputStream) throws IOException new GzipCompressorInputStream(Files.newInputStream(this.path))); TarArchiveOutputStream output = new TarArchiveOutputStream(outputStream)) { writeBasePathEntries(output, basePath); - TarArchiveEntry entry = tar.getNextTarEntry(); + TarArchiveEntry entry = tar.getNextEntry(); while (entry != null) { entry.setName(basePath + "/" + entry.getName()); output.putArchiveEntry(entry); StreamUtils.copy(tar, output); output.closeArchiveEntry(); - entry = tar.getNextTarEntry(); + entry = tar.getNextEntry(); } output.finish(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java index d6c788259ad0..8847290f6c05 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java @@ -296,7 +296,7 @@ public void exportLayerFiles(ImageReference reference, IOBiConsumer layerFiles = new HashMap<>(); try (TarArchiveInputStream tar = new TarArchiveInputStream(response.getContent())) { - TarArchiveEntry entry = tar.getNextTarEntry(); + TarArchiveEntry entry = tar.getNextEntry(); while (entry != null) { if (entry.getName().equals("manifest.json")) { manifest = readManifest(tar); @@ -304,7 +304,7 @@ public void exportLayerFiles(ImageReference reference, IOBiConsumer entries = new ArrayList<>(); - TarArchiveEntry entry = tar.getNextTarEntry(); + TarArchiveEntry entry = tar.getNextEntry(); while (entry != null) { entries.add(entry); - entry = tar.getNextTarEntry(); + entry = tar.getNextEntry(); } assertThat(entries).extracting("name", "mode") .containsExactlyInAnyOrder(tuple("/cnb/", 0755), tuple("/cnb/buildpacks/", 0755), diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java index 2ad43f3ecc10..cebc8c0bd477 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -213,10 +213,10 @@ private void assertAppliesExpectedLayers(Buildpack buildpack) throws IOException byte[] content = layers.get(0).toByteArray(); List entries = new ArrayList<>(); try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) { - TarArchiveEntry entry = tar.getNextTarEntry(); + TarArchiveEntry entry = tar.getNextEntry(); while (entry != null) { entries.add(entry); - entry = tar.getNextTarEntry(); + entry = tar.getNextEntry(); } } assertThat(entries).extracting("name", "mode") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java index 2bb460b85cd1..6bb991342663 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -336,10 +336,10 @@ void exportLayersExportsLayerTars() throws Exception { archive.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { contents.add(name, entry.getName()); - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } }); @@ -364,10 +364,10 @@ void exportLayersWithSymlinksExportsLayerTars() throws Exception { archive.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { contents.add(name, entry.getName()); - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } }); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java index 318bf7985c54..123f49bbcdd9 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -54,14 +54,14 @@ void fromImageWritesToValidArchiveTar() throws Exception { try (TarArchiveInputStream tar = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { for (int i = 0; i < EXISTING_IMAGE_LAYER_COUNT; i++) { - TarArchiveEntry blankEntry = tar.getNextTarEntry(); + TarArchiveEntry blankEntry = tar.getNextEntry(); assertThat(blankEntry.getName()).isEqualTo("blank_" + i); } - TarArchiveEntry layerEntry = tar.getNextTarEntry(); + TarArchiveEntry layerEntry = tar.getNextEntry(); byte[] layerContent = read(tar, layerEntry.getSize()); - TarArchiveEntry configEntry = tar.getNextTarEntry(); + TarArchiveEntry configEntry = tar.getNextEntry(); byte[] configContent = read(tar, configEntry.getSize()); - TarArchiveEntry manifestEntry = tar.getNextTarEntry(); + TarArchiveEntry manifestEntry = tar.getNextEntry(); byte[] manifestContent = read(tar, manifestEntry.getSize()); assertExpectedLayer(layerEntry, layerContent); assertExpectedConfig(configEntry, configContent); @@ -72,7 +72,7 @@ void fromImageWritesToValidArchiveTar() throws Exception { private void assertExpectedLayer(TarArchiveEntry entry, byte[] content) throws Exception { assertThat(entry.getName()).isEqualTo("bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar"); try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) { - TarArchiveEntry contentEntry = tar.getNextTarEntry(); + TarArchiveEntry contentEntry = tar.getNextEntry(); assertThat(contentEntry.getName()).isEqualTo("/spring/"); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java index db72d542c7c6..bad2124fb8d5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -61,9 +61,9 @@ void ofCreatesLayer() throws Exception { layer.writeTo(outputStream); try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - assertThat(tarStream.getNextTarEntry().getName()).isEqualTo("/directory/"); - assertThat(tarStream.getNextTarEntry().getName()).isEqualTo("/directory/file"); - assertThat(tarStream.getNextTarEntry()).isNull(); + assertThat(tarStream.getNextEntry().getName()).isEqualTo("/directory/"); + assertThat(tarStream.getNextEntry().getName()).isEqualTo("/directory/file"); + assertThat(tarStream.getNextEntry()).isNull(); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java index 0f5be72a0f75..1a587eb5be61 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -58,10 +58,10 @@ void ofWritesTarContent() throws Exception { try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { List entries = new ArrayList<>(); - TarArchiveEntry entry = tarStream.getNextTarEntry(); + TarArchiveEntry entry = tarStream.getNextEntry(); while (entry != null) { entries.add(entry); - entry = tarStream.getNextTarEntry(); + entry = tarStream.getNextEntry(); } assertThat(entries).hasSize(6); assertThat(entries.get(0).getName()).isEqualTo("/workspace/"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java index 847abc77fa81..f212ad69fe56 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -44,8 +44,8 @@ void writesTarArchive() throws Exception { } try (TarArchiveInputStream tarInputStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - TarArchiveEntry directoryEntry = tarInputStream.getNextTarEntry(); - TarArchiveEntry fileEntry = tarInputStream.getNextTarEntry(); + TarArchiveEntry directoryEntry = tarInputStream.getNextEntry(); + TarArchiveEntry fileEntry = tarInputStream.getNextEntry(); byte[] fileContent = new byte[(int) fileEntry.getSize()]; tarInputStream.read(fileContent); assertThat(tarInputStream.getNextEntry()).isNull(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java index cd11ef39298f..48c2f6f70e11 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -67,11 +67,11 @@ void writeToAdaptsContent() throws Exception { tarArchive.writeTo(outputStream); try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - TarArchiveEntry dirEntry = tarStream.getNextTarEntry(); + TarArchiveEntry dirEntry = tarStream.getNextEntry(); assertThat(dirEntry.getName()).isEqualTo("spring/"); assertThat(dirEntry.getLongUserId()).isEqualTo(123); assertThat(dirEntry.getLongGroupId()).isEqualTo(456); - TarArchiveEntry fileEntry = tarStream.getNextTarEntry(); + TarArchiveEntry fileEntry = tarStream.getNextEntry(); assertThat(fileEntry.getName()).isEqualTo("spring/boot"); assertThat(fileEntry.getLongUserId()).isEqualTo(123); assertThat(fileEntry.getLongGroupId()).isEqualTo(456); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java index d30629bb32de..292dd2bbd52b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -195,7 +195,7 @@ private List tarEntryNames(File distribution) throws IOException { List entryNames = new ArrayList<>(); try (TarArchiveInputStream input = new TarArchiveInputStream(new FileInputStream(distribution))) { TarArchiveEntry entry; - while ((entry = input.getNextTarEntry()) != null) { + while ((entry = input.getNextEntry()) != null) { entryNames.add(entry.getName()); } } @@ -205,7 +205,7 @@ private List tarEntryNames(File distribution) throws IOException { private void tarEntries(File distribution, Consumer consumer) throws IOException { try (TarArchiveInputStream input = new TarArchiveInputStream(new FileInputStream(distribution))) { TarArchiveEntry entry; - while ((entry = input.getNextTarEntry()) != null) { + while ((entry = input.getNextEntry()) != null) { consumer.accept(entry); } } diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java index 39b879011cb9..fc5f9509412b 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. @@ -80,12 +80,12 @@ public ListAssert entries() { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { if (!entry.isDirectory()) { entryNames.add(entry.getName().replaceFirst("^/workspace/", "")); } - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } } @@ -101,7 +101,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { if (entry.getName().equals(name)) { ByteArrayOutputStream entryOut = new ByteArrayOutputStream(); @@ -109,7 +109,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { assertConsumer.accept(new JsonContentAssert(LayerContentAssert.class, entryOut.toString())); return; } - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } failWithMessage("Expected JSON entry '%s' in layer with digest '%s'", name, this.actual.getId()); From 50c44e301a03e10bf509b173733ea23e3d456454 Mon Sep 17 00:00:00 2001 From: tish Date: Thu, 25 Jan 2024 07:59:49 +0400 Subject: [PATCH 019/182] Prevent double registration of event publisher registrar See gh-39297 --- .../testcontainers/properties/TestcontainersPropertySource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java index 1994303645ef..d52cc0c8d51b 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java @@ -115,7 +115,7 @@ private static DynamicPropertyRegistry attach(Environment environment, Applicati if (eventPublisher != null) { propertySource.addEventPublisher(eventPublisher); } - else if (registry != null) { + else if (registry != null && !registry.containsBeanDefinition(EventPublisherRegistrar.NAME)) { registry.registerBeanDefinition(EventPublisherRegistrar.NAME, new RootBeanDefinition( EventPublisherRegistrar.class, () -> new EventPublisherRegistrar(environment))); } From 61ca87f7a4960353c1e7699a9567c666fc6c2231 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 30 Jan 2024 16:02:38 +0000 Subject: [PATCH 020/182] Polish "Prevent double registration of event publisher registrar" See gh-39297 --- .../TestcontainersPropertySource.java | 2 +- .../TestcontainersPropertySourceTests.java | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java index d52cc0c8d51b..10bcb2a9864c 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java @@ -138,7 +138,7 @@ static TestcontainersPropertySource getOrAdd(ConfigurableEnvironment environment * to the {@link TestcontainersPropertySource}. This class is a * {@link BeanFactoryPostProcessor} so that it is initialized as early as possible. */ - private static class EventPublisherRegistrar implements BeanFactoryPostProcessor, ApplicationEventPublisherAware { + static class EventPublisherRegistrar implements BeanFactoryPostProcessor, ApplicationEventPublisherAware { static final String NAME = EventPublisherRegistrar.class.getName(); diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java index 4dce61ffc942..e11488b349c3 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java @@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.testcontainers.properties.TestcontainersPropertySource.EventPublisherRegistrar; import org.springframework.context.ApplicationEvent; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.env.EnumerablePropertySource; @@ -42,6 +44,13 @@ class TestcontainersPropertySourceTests { private MockEnvironment environment = new MockEnvironment(); + private GenericApplicationContext context = new GenericApplicationContext(); + + TestcontainersPropertySourceTests() { + ((DefaultListableBeanFactory) this.context.getBeanFactory()).setAllowBeanDefinitionOverriding(false); + this.context.setEnvironment(this.environment); + } + @Test void getPropertyWhenHasValueSupplierReturnsSuppliedValue() { DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); @@ -90,14 +99,14 @@ void getSourceReturnsImmutableSource() { } @Test - void attachWhenNotAttachedAttaches() { + void attachToEnvironmentWhenNotAttachedAttaches() { TestcontainersPropertySource.attach(this.environment); PropertySource propertySource = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); assertThat(propertySource).isNotNull(); } @Test - void attachWhenAlreadyAttachedReturnsExisting() { + void attachToEnvironmentWhenAlreadyAttachedReturnsExisting() { DynamicPropertyRegistry r1 = TestcontainersPropertySource.attach(this.environment); PropertySource p1 = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); DynamicPropertyRegistry r2 = TestcontainersPropertySource.attach(this.environment); @@ -106,6 +115,24 @@ void attachWhenAlreadyAttachedReturnsExisting() { assertThat(p1).isSameAs(p2); } + @Test + void attachToEnvironmentAndContextWhenNotAttachedAttaches() { + TestcontainersPropertySource.attach(this.environment, this.context); + PropertySource propertySource = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + assertThat(propertySource).isNotNull(); + assertThat(this.context.containsBean(EventPublisherRegistrar.NAME)); + } + + @Test + void attachToEnvironmentAndContextWhenAlreadyAttachedReturnsExisting() { + DynamicPropertyRegistry r1 = TestcontainersPropertySource.attach(this.environment, this.context); + PropertySource p1 = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + DynamicPropertyRegistry r2 = TestcontainersPropertySource.attach(this.environment, this.context); + PropertySource p2 = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + assertThat(r1).isSameAs(r2); + assertThat(p1).isSameAs(p2); + } + @Test void getPropertyPublishesEvent() { try (GenericApplicationContext applicationContext = new GenericApplicationContext()) { From a620d348ad74daa15edfbcf5e9098e4f9694fb86 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 30 Jan 2024 16:00:59 -0600 Subject: [PATCH 021/182] Fix exporting of Docker image layers The logic to extract layers from a downloaded Docker image assumed that the layer entries in the image tar archive always had the file extension `.tar`. This was the case with Docker and other compatible daemons until Docker 25.0. With this commit, the extension is no longer assumed, but any entries listed in `manifest.json` will be recognized. Fixes gh-39323 --- .../buildpack/platform/docker/DockerApi.java | 43 ++++++++++--------- .../platform/build/ImageBuildpackTests.java | 2 + .../platform/docker/DockerApiTests.java | 1 + 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java index 8847290f6c05..ad53e823d278 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java @@ -18,6 +18,7 @@ import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -30,9 +31,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -293,29 +292,20 @@ public void exportLayerFiles(ImageReference reference, IOBiConsumer layerFiles = new HashMap<>(); - try (TarArchiveInputStream tar = new TarArchiveInputStream(response.getContent())) { + Path exportFile = copyToTemp(response.getContent()); + ImageArchiveManifest manifest = getManifest(reference, exportFile); + try (TarArchiveInputStream tar = new TarArchiveInputStream(new FileInputStream(exportFile.toFile()))) { TarArchiveEntry entry = tar.getNextEntry(); while (entry != null) { - if (entry.getName().equals("manifest.json")) { - manifest = readManifest(tar); - } - if (entry.getName().endsWith(".tar")) { - layerFiles.put(entry.getName(), copyToTemp(tar)); + if (manifestContainsLayerEntry(manifest, entry.getName())) { + Path layerFile = copyToTemp(tar); + exports.accept(entry.getName(), layerFile); + Files.delete(layerFile); } entry = tar.getNextEntry(); } } - Assert.notNull(manifest, "Manifest not found in image " + reference); - for (Map.Entry entry : layerFiles.entrySet()) { - String name = entry.getKey(); - Path path = entry.getValue(); - if (manifestContainsLayerEntry(manifest, name)) { - exports.accept(name, path); - } - Files.delete(path); - } + Files.delete(exportFile); } /** @@ -355,13 +345,26 @@ public void tag(ImageReference sourceReference, ImageReference targetReference) http().post(uri).close(); } + private ImageArchiveManifest getManifest(ImageReference reference, Path exportFile) throws IOException { + try (TarArchiveInputStream tar = new TarArchiveInputStream(new FileInputStream(exportFile.toFile()))) { + TarArchiveEntry entry = tar.getNextEntry(); + while (entry != null) { + if (entry.getName().equals("manifest.json")) { + return readManifest(tar); + } + entry = tar.getNextEntry(); + } + } + throw new IllegalArgumentException("Manifest not found in image " + reference); + } + private ImageArchiveManifest readManifest(TarArchiveInputStream tar) throws IOException { String manifestContent = new BufferedReader(new InputStreamReader(tar, StandardCharsets.UTF_8)).lines() .collect(Collectors.joining()); return ImageArchiveManifest.of(new ByteArrayInputStream(manifestContent.getBytes(StandardCharsets.UTF_8))); } - private Path copyToTemp(TarArchiveInputStream in) throws IOException { + private Path copyToTemp(InputStream in) throws IOException { Path path = Files.createTempFile("create-builder-scratch-", null); try (OutputStream out = Files.newOutputStream(path)) { StreamUtils.copy(in, out); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java index cebc8c0bd477..7978de12eb29 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -189,6 +190,7 @@ private Object withMockLayers(InvocationOnMock invocation) { tarOut.finish(); } consumer.accept("test", tarFile.toPath()); + Files.delete(tarFile.toPath()); } catch (IOException ex) { fail("Error writing mock layers", ex); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java index 6bb991342663..f751ada70cdd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java @@ -382,6 +382,7 @@ void exportLayersWithSymlinksExportsLayerTars() throws Exception { } @Test + @SuppressWarnings("removal") void exportLayerFilesDeletesTempFiles() throws Exception { ImageReference reference = ImageReference.of("gcr.io/paketo-buildpacks/builder:base"); URI exportUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder:base/get"); From 231aa014fa2413415c173cdc9d63dc1158e8bb6e Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 31 Jan 2024 08:35:11 +0100 Subject: [PATCH 022/182] Upgrade to Testcontainers 1.19.4 Closes gh-39353 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 37e4674049e8..1c3596392674 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1641,7 +1641,7 @@ bom { ] } } - library("Testcontainers", "1.19.3") { + library("Testcontainers", "1.19.4") { group("org.testcontainers") { imports = [ "testcontainers-bom" From c02dd14c66b4004d0e1db65855c364ac3e2f5a6b Mon Sep 17 00:00:00 2001 From: JonasG Date: Thu, 25 Jan 2024 15:56:08 +0100 Subject: [PATCH 023/182] Use generic wildcard for Pulsar beans See gh-39308 --- .../pulsar/PulsarAutoConfiguration.java | 5 +++-- .../pulsar/PulsarAutoConfigurationTests.java | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfiguration.java index c60565b5918f..fbe4f3fcc5a5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfiguration.java @@ -65,6 +65,7 @@ * @author Soby Chacko * @author Alexander Preuß * @author Phillip Webb + * @author Jonas Geiregat * @since 3.2.0 */ @AutoConfiguration @@ -131,7 +132,7 @@ PulsarTemplate pulsarTemplate(PulsarProducerFactory pulsarProducerFactory, @Bean @ConditionalOnMissingBean(PulsarConsumerFactory.class) - DefaultPulsarConsumerFactory pulsarConsumerFactory(PulsarClient pulsarClient, + DefaultPulsarConsumerFactory pulsarConsumerFactory(PulsarClient pulsarClient, ObjectProvider> customizersProvider) { List> customizers = new ArrayList<>(); customizers.add(this.propertiesMapper::customizeConsumerBuilder); @@ -150,7 +151,7 @@ private void applyConsumerBuilderCustomizers(List> @Bean @ConditionalOnMissingBean(name = "pulsarListenerContainerFactory") - ConcurrentPulsarListenerContainerFactory pulsarListenerContainerFactory( + ConcurrentPulsarListenerContainerFactory pulsarListenerContainerFactory( PulsarConsumerFactory pulsarConsumerFactory, SchemaResolver schemaResolver, TopicResolver topicResolver, Environment environment) { PulsarContainerProperties containerProperties = new PulsarContainerProperties(); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java index 7e56f4129ead..b4691ecbfbc6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java @@ -34,6 +34,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.TestConfiguration; @@ -373,6 +374,14 @@ void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { }); } + @Test + void injectsExpectedBeanWithExplicitGenericType() { + this.contextRunner.withBean(ExplicitGenericTypeConfig.class) + .run((context) -> assertThat(context).getBean(ExplicitGenericTypeConfig.class) + .hasFieldOrPropertyWithValue("consumerFactory", context.getBean(PulsarConsumerFactory.class)) + .hasFieldOrPropertyWithValue("containerFactory", context.getBean(ConcurrentPulsarListenerContainerFactory.class))); + } + @TestConfiguration(proxyBeanMethods = false) static class ConsumerBuilderCustomizersConfig { @@ -390,6 +399,16 @@ ConsumerBuilderCustomizer customizerBar() { } + static class ExplicitGenericTypeConfig { + @Autowired + PulsarConsumerFactory consumerFactory; + + @Autowired + ConcurrentPulsarListenerContainerFactory containerFactory; + + static class TestType {} + } + } @Nested From cee249197fbf8eaebbbe91f9f25dcba33ee8e920 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 31 Jan 2024 09:54:18 +0100 Subject: [PATCH 024/182] Polish "Use generic wildcard for Pulsar beans" See gh-39308 --- .../pulsar/PulsarAutoConfigurationTests.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java index b4691ecbfbc6..bade49b3b286 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java @@ -377,9 +377,10 @@ void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { @Test void injectsExpectedBeanWithExplicitGenericType() { this.contextRunner.withBean(ExplicitGenericTypeConfig.class) - .run((context) -> assertThat(context).getBean(ExplicitGenericTypeConfig.class) - .hasFieldOrPropertyWithValue("consumerFactory", context.getBean(PulsarConsumerFactory.class)) - .hasFieldOrPropertyWithValue("containerFactory", context.getBean(ConcurrentPulsarListenerContainerFactory.class))); + .run((context) -> assertThat(context).getBean(ExplicitGenericTypeConfig.class) + .hasFieldOrPropertyWithValue("consumerFactory", context.getBean(PulsarConsumerFactory.class)) + .hasFieldOrPropertyWithValue("containerFactory", + context.getBean(ConcurrentPulsarListenerContainerFactory.class))); } @TestConfiguration(proxyBeanMethods = false) @@ -400,13 +401,17 @@ ConsumerBuilderCustomizer customizerBar() { } static class ExplicitGenericTypeConfig { + @Autowired PulsarConsumerFactory consumerFactory; @Autowired ConcurrentPulsarListenerContainerFactory containerFactory; - static class TestType {} + static class TestType { + + } + } } From dd082c6c2119eeedd017848fc4f8809f61ee5979 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 31 Jan 2024 17:21:32 +0000 Subject: [PATCH 025/182] Revert "Upgrade to Commons Compress 1.25.0" This reverts commit 1c2a622f7fcef9ebd5cb74ade3869a3dfc3ca6af. See gh-39148 --- spring-boot-project/spring-boot-parent/build.gradle | 2 +- .../boot/buildpack/platform/build/ImageBuildpack.java | 4 ++-- .../buildpack/platform/build/TarGzipBuildpack.java | 4 ++-- .../boot/buildpack/platform/docker/DockerApi.java | 8 ++++---- .../platform/build/DirectoryBuildpackTests.java | 4 ++-- .../buildpack/platform/build/ImageBuildpackTests.java | 4 ++-- .../boot/buildpack/platform/docker/DockerApiTests.java | 8 ++++---- .../platform/docker/type/ImageArchiveTests.java | 10 +++++----- .../buildpack/platform/docker/type/LayerTests.java | 6 +++--- .../boot/buildpack/platform/io/TarArchiveTests.java | 4 ++-- .../buildpack/platform/io/TarLayoutWriterTests.java | 4 ++-- .../buildpack/platform/io/ZipFileTarArchiveTests.java | 4 ++-- .../ApplicationPluginActionIntegrationTests.java | 4 ++-- .../boot/image/assertions/ImageAssert.java | 8 ++++---- 14 files changed, 37 insertions(+), 37 deletions(-) diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index cf30f9dd5871..48b8d88b3b6f 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -34,7 +34,7 @@ bom { ] } } - library("Commons Compress", "1.25.0") { + library("Commons Compress", "1.21") { group("org.apache.commons") { modules = [ "commons-compress" diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java index 827f4a8da015..31c84cefc10e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ImageBuildpack.java @@ -131,12 +131,12 @@ private void copyLayerTar(Path path, OutputStream out) throws IOException { try (TarArchiveInputStream tarIn = new TarArchiveInputStream(Files.newInputStream(path)); TarArchiveOutputStream tarOut = new TarArchiveOutputStream(out)) { tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); - TarArchiveEntry entry = tarIn.getNextEntry(); + TarArchiveEntry entry = tarIn.getNextTarEntry(); while (entry != null) { tarOut.putArchiveEntry(entry); StreamUtils.copy(tarIn, tarOut); tarOut.closeArchiveEntry(); - entry = tarIn.getNextEntry(); + entry = tarIn.getNextTarEntry(); } tarOut.finish(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java index 4174166f3d27..b485552efcd8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/TarGzipBuildpack.java @@ -90,13 +90,13 @@ private void copyAndRebaseEntries(OutputStream outputStream) throws IOException new GzipCompressorInputStream(Files.newInputStream(this.path))); TarArchiveOutputStream output = new TarArchiveOutputStream(outputStream)) { writeBasePathEntries(output, basePath); - TarArchiveEntry entry = tar.getNextEntry(); + TarArchiveEntry entry = tar.getNextTarEntry(); while (entry != null) { entry.setName(basePath + "/" + entry.getName()); output.putArchiveEntry(entry); StreamUtils.copy(tar, output); output.closeArchiveEntry(); - entry = tar.getNextEntry(); + entry = tar.getNextTarEntry(); } output.finish(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java index ad53e823d278..4efc4a0c7cb2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java @@ -295,14 +295,14 @@ public void exportLayerFiles(ImageReference reference, IOBiConsumer entries = new ArrayList<>(); - TarArchiveEntry entry = tar.getNextEntry(); + TarArchiveEntry entry = tar.getNextTarEntry(); while (entry != null) { entries.add(entry); - entry = tar.getNextEntry(); + entry = tar.getNextTarEntry(); } assertThat(entries).extracting("name", "mode") .containsExactlyInAnyOrder(tuple("/cnb/", 0755), tuple("/cnb/buildpacks/", 0755), diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java index 7978de12eb29..f42d6ee60b60 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ImageBuildpackTests.java @@ -215,10 +215,10 @@ private void assertAppliesExpectedLayers(Buildpack buildpack) throws IOException byte[] content = layers.get(0).toByteArray(); List entries = new ArrayList<>(); try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) { - TarArchiveEntry entry = tar.getNextEntry(); + TarArchiveEntry entry = tar.getNextTarEntry(); while (entry != null) { entries.add(entry); - entry = tar.getNextEntry(); + entry = tar.getNextTarEntry(); } } assertThat(entries).extracting("name", "mode") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java index f751ada70cdd..814914861b2d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java @@ -336,10 +336,10 @@ void exportLayersExportsLayerTars() throws Exception { archive.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { contents.add(name, entry.getName()); - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } }); @@ -364,10 +364,10 @@ void exportLayersWithSymlinksExportsLayerTars() throws Exception { archive.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { contents.add(name, entry.getName()); - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } }); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java index 123f49bbcdd9..20717b8a5d7c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java @@ -54,14 +54,14 @@ void fromImageWritesToValidArchiveTar() throws Exception { try (TarArchiveInputStream tar = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { for (int i = 0; i < EXISTING_IMAGE_LAYER_COUNT; i++) { - TarArchiveEntry blankEntry = tar.getNextEntry(); + TarArchiveEntry blankEntry = tar.getNextTarEntry(); assertThat(blankEntry.getName()).isEqualTo("blank_" + i); } - TarArchiveEntry layerEntry = tar.getNextEntry(); + TarArchiveEntry layerEntry = tar.getNextTarEntry(); byte[] layerContent = read(tar, layerEntry.getSize()); - TarArchiveEntry configEntry = tar.getNextEntry(); + TarArchiveEntry configEntry = tar.getNextTarEntry(); byte[] configContent = read(tar, configEntry.getSize()); - TarArchiveEntry manifestEntry = tar.getNextEntry(); + TarArchiveEntry manifestEntry = tar.getNextTarEntry(); byte[] manifestContent = read(tar, manifestEntry.getSize()); assertExpectedLayer(layerEntry, layerContent); assertExpectedConfig(configEntry, configContent); @@ -72,7 +72,7 @@ void fromImageWritesToValidArchiveTar() throws Exception { private void assertExpectedLayer(TarArchiveEntry entry, byte[] content) throws Exception { assertThat(entry.getName()).isEqualTo("bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar"); try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) { - TarArchiveEntry contentEntry = tar.getNextEntry(); + TarArchiveEntry contentEntry = tar.getNextTarEntry(); assertThat(contentEntry.getName()).isEqualTo("/spring/"); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java index bad2124fb8d5..b07861d7fb55 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/LayerTests.java @@ -61,9 +61,9 @@ void ofCreatesLayer() throws Exception { layer.writeTo(outputStream); try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - assertThat(tarStream.getNextEntry().getName()).isEqualTo("/directory/"); - assertThat(tarStream.getNextEntry().getName()).isEqualTo("/directory/file"); - assertThat(tarStream.getNextEntry()).isNull(); + assertThat(tarStream.getNextTarEntry().getName()).isEqualTo("/directory/"); + assertThat(tarStream.getNextTarEntry().getName()).isEqualTo("/directory/file"); + assertThat(tarStream.getNextTarEntry()).isNull(); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java index 1a587eb5be61..615dc03a0fa6 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarArchiveTests.java @@ -58,10 +58,10 @@ void ofWritesTarContent() throws Exception { try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { List entries = new ArrayList<>(); - TarArchiveEntry entry = tarStream.getNextEntry(); + TarArchiveEntry entry = tarStream.getNextTarEntry(); while (entry != null) { entries.add(entry); - entry = tarStream.getNextEntry(); + entry = tarStream.getNextTarEntry(); } assertThat(entries).hasSize(6); assertThat(entries.get(0).getName()).isEqualTo("/workspace/"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java index f212ad69fe56..1bb1d87fdbd2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/TarLayoutWriterTests.java @@ -44,8 +44,8 @@ void writesTarArchive() throws Exception { } try (TarArchiveInputStream tarInputStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - TarArchiveEntry directoryEntry = tarInputStream.getNextEntry(); - TarArchiveEntry fileEntry = tarInputStream.getNextEntry(); + TarArchiveEntry directoryEntry = tarInputStream.getNextTarEntry(); + TarArchiveEntry fileEntry = tarInputStream.getNextTarEntry(); byte[] fileContent = new byte[(int) fileEntry.getSize()]; tarInputStream.read(fileContent); assertThat(tarInputStream.getNextEntry()).isNull(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java index 48c2f6f70e11..a1c887510d26 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/io/ZipFileTarArchiveTests.java @@ -67,11 +67,11 @@ void writeToAdaptsContent() throws Exception { tarArchive.writeTo(outputStream); try (TarArchiveInputStream tarStream = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { - TarArchiveEntry dirEntry = tarStream.getNextEntry(); + TarArchiveEntry dirEntry = tarStream.getNextTarEntry(); assertThat(dirEntry.getName()).isEqualTo("spring/"); assertThat(dirEntry.getLongUserId()).isEqualTo(123); assertThat(dirEntry.getLongGroupId()).isEqualTo(456); - TarArchiveEntry fileEntry = tarStream.getNextEntry(); + TarArchiveEntry fileEntry = tarStream.getNextTarEntry(); assertThat(fileEntry.getName()).isEqualTo("spring/boot"); assertThat(fileEntry.getLongUserId()).isEqualTo(123); assertThat(fileEntry.getLongGroupId()).isEqualTo(456); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java index 292dd2bbd52b..6d2daf320a1a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/ApplicationPluginActionIntegrationTests.java @@ -195,7 +195,7 @@ private List tarEntryNames(File distribution) throws IOException { List entryNames = new ArrayList<>(); try (TarArchiveInputStream input = new TarArchiveInputStream(new FileInputStream(distribution))) { TarArchiveEntry entry; - while ((entry = input.getNextEntry()) != null) { + while ((entry = input.getNextTarEntry()) != null) { entryNames.add(entry.getName()); } } @@ -205,7 +205,7 @@ private List tarEntryNames(File distribution) throws IOException { private void tarEntries(File distribution, Consumer consumer) throws IOException { try (TarArchiveInputStream input = new TarArchiveInputStream(new FileInputStream(distribution))) { TarArchiveEntry entry; - while ((entry = input.getNextEntry()) != null) { + while ((entry = input.getNextTarEntry()) != null) { consumer.accept(entry); } } diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java index fc5f9509412b..ce326c1702ba 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java @@ -80,12 +80,12 @@ public ListAssert entries() { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { if (!entry.isDirectory()) { entryNames.add(entry.getName().replaceFirst("^/workspace/", "")); } - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } } @@ -101,7 +101,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { if (entry.getName().equals(name)) { ByteArrayOutputStream entryOut = new ByteArrayOutputStream(); @@ -109,7 +109,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { assertConsumer.accept(new JsonContentAssert(LayerContentAssert.class, entryOut.toString())); return; } - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } failWithMessage("Expected JSON entry '%s' in layer with digest '%s'", name, this.actual.getId()); From 0df3ec2ef37d0c382376839ceef5911ca116a4af Mon Sep 17 00:00:00 2001 From: Onur Kagan Ozcan Date: Wed, 31 Jan 2024 16:49:13 +0300 Subject: [PATCH 026/182] Remove System.out usage from Jetty GracefulShutdown See gh-39360 --- .../boot/web/embedded/jetty/GracefulShutdown.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java index 8ccd5d26e56c..987583bc2128 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/GracefulShutdown.java @@ -36,6 +36,7 @@ * Handles Jetty graceful shutdown. * * @author Andy Wilkinson + * @author Onur Kagan Ozcan */ final class GracefulShutdown { @@ -99,7 +100,6 @@ private void awaitShutdown(GracefulShutdownCallback callback) { while (this.shuttingDown && this.activeRequests.get() > 0) { sleep(100); } - System.out.println(this.activeRequests.get()); this.shuttingDown = false; long activeRequests = this.activeRequests.get(); if (activeRequests == 0) { From 2b85cb03566b88d616fa51d970be6425c4d454d1 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 1 Feb 2024 10:12:33 +0000 Subject: [PATCH 027/182] Stop managing version of commons-compress where it isn't needed Closes gh-39367 --- gradle.properties | 1 + spring-boot-project/spring-boot-parent/build.gradle | 7 ------- .../spring-boot-buildpack-platform/build.gradle | 2 +- .../spring-boot-gradle-plugin/build.gradle | 2 +- .../spring-boot-loader-tools/build.gradle | 2 +- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4a739e43a364..718ab5b766f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 assertjVersion=3.24.2 commonsCodecVersion=1.15 +commonsCompressVersion=1.21 hamcrestVersion=2.2 jacksonVersion=2.15.3 junitJupiterVersion=5.9.3 diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 48b8d88b3b6f..2e8a3a3315e0 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -34,13 +34,6 @@ bom { ] } } - library("Commons Compress", "1.21") { - group("org.apache.commons") { - modules = [ - "commons-compress" - ] - } - } library("Commons FileUpload", "1.5") { group("commons-fileupload") { modules = [ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle index d6b393c6819e..0e448630278b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle @@ -22,7 +22,7 @@ dependencies { api("com.fasterxml.jackson.core:jackson-databind") api("com.fasterxml.jackson.module:jackson-module-parameter-names") api("net.java.dev.jna:jna-platform") - api("org.apache.commons:commons-compress") + api("org.apache.commons:commons-compress:$commonsCompressVersion") api("org.apache.httpcomponents.client5:httpclient5") api("org.springframework:spring-core") api("org.tomlj:tomlj:1.0.0") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle index 48e174123a43..6abef56e5b02 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle @@ -34,7 +34,7 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools")) implementation("io.spring.gradle:dependency-management-plugin") - implementation("org.apache.commons:commons-compress") + implementation("org.apache.commons:commons-compress:$commonsCompressVersion") implementation("org.springframework:spring-core") optional("org.graalvm.buildtools:native-gradle-plugin") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle index c6b187317071..738f53333820 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle @@ -20,7 +20,7 @@ configurations { } dependencies { - api("org.apache.commons:commons-compress") + api("org.apache.commons:commons-compress:$commonsCompressVersion") api("org.springframework:spring-core") compileOnly("ch.qos.logback:logback-classic") From c3664f372c4de8e2702e152e6cf99030f1b64b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 2 Feb 2024 15:21:33 +0100 Subject: [PATCH 028/182] Polish See gh-39382 --- ...AuditEventsEndpointDocumentationTests.java | 8 +++--- .../BeansEndpointDocumentationTests.java | 5 ++-- .../CachesEndpointDocumentationTests.java | 6 ++-- ...tionsReportEndpointDocumentationTests.java | 28 +++---------------- .../FlywayEndpointDocumentationTests.java | 5 ++-- .../HealthEndpointDocumentationTests.java | 3 +- ...tpExchangesEndpointDocumentationTests.java | 10 +++---- .../LiquibaseEndpointDocumentationTests.java | 5 ++-- .../LoggersEndpointDocumentationTests.java | 21 ++++++-------- ...ngsEndpointReactiveDocumentationTests.java | 11 ++++---- ...ingsEndpointServletDocumentationTests.java | 9 +++--- .../QuartzEndpointDocumentationTests.java | 18 ++++++------ ...eduledTasksEndpointDocumentationTests.java | 6 ++-- .../SessionsEndpointDocumentationTests.java | 3 +- .../ShutdownEndpointDocumentationTests.java | 5 ++-- 15 files changed, 52 insertions(+), 91 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/AuditEventsEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/AuditEventsEndpointDocumentationTests.java index 99d2b4452810..aaf3805f91d0 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/AuditEventsEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/AuditEventsEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -18,8 +18,8 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; -import java.util.Arrays; import java.util.Collections; +import java.util.List; import org.junit.jupiter.api.Test; @@ -56,7 +56,7 @@ class AuditEventsEndpointDocumentationTests extends MockMvcEndpointDocumentation void allAuditEvents() throws Exception { String queryTimestamp = "2017-11-07T09:37Z"; given(this.repository.find(any(), any(), any())) - .willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap()))); + .willReturn(List.of(new AuditEvent("alice", "logout", Collections.emptyMap()))); this.mockMvc.perform(get("/actuator/auditevents").param("after", queryTimestamp)) .andExpect(status().isOk()) .andDo(document("auditevents/all", @@ -72,7 +72,7 @@ void filteredAuditEvents() throws Exception { OffsetDateTime now = OffsetDateTime.now(); String queryTimestamp = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(now); given(this.repository.find("alice", now.toInstant(), "logout")) - .willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap()))); + .willReturn(List.of(new AuditEvent("alice", "logout", Collections.emptyMap()))); this.mockMvc .perform(get("/actuator/auditevents").param("principal", "alice") .param("after", queryTimestamp) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/BeansEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/BeansEndpointDocumentationTests.java index 282eb162f18b..4eb3fb8bcd4e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/BeansEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/BeansEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -50,7 +49,7 @@ class BeansEndpointDocumentationTests extends MockMvcEndpointDocumentationTests @Test void beans() throws Exception { - List beanFields = Arrays.asList(fieldWithPath("aliases").description("Names of any aliases."), + List beanFields = List.of(fieldWithPath("aliases").description("Names of any aliases."), fieldWithPath("scope").description("Scope of the bean."), fieldWithPath("type").description("Fully qualified type of the bean."), fieldWithPath("resource").description("Resource in which the bean was defined, if any.") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/CachesEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/CachesEndpointDocumentationTests.java index ba1fc9346e64..44cf427a2967 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/CachesEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/CachesEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -50,8 +49,7 @@ */ class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentationTests { - private static final List levelFields = Arrays.asList( - fieldWithPath("name").description("Cache name."), + private static final List levelFields = List.of(fieldWithPath("name").description("Cache name."), fieldWithPath("cacheManager").description("Cache manager name."), fieldWithPath("target").description("Fully qualified name of the native cache.")); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ConditionsReportEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ConditionsReportEndpointDocumentationTests.java index 3e36dff8ad78..58586569d147 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ConditionsReportEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ConditionsReportEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,13 +16,10 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.List; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; @@ -30,13 +27,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.restdocs.payload.FieldDescriptor; import org.springframework.restdocs.payload.JsonFieldType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -51,26 +44,13 @@ */ class ConditionsReportEndpointDocumentationTests extends MockMvcEndpointDocumentationTests { - private MockMvc mockMvc; - - @Autowired - private WebApplicationContext applicationContext; - - @Override - @BeforeEach - void setup(RestDocumentationContextProvider restDocumentation) { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext) - .apply(MockMvcRestDocumentation.documentationConfiguration(restDocumentation).uris()) - .build(); - } - @Test void conditions() throws Exception { - List positiveMatchFields = Arrays.asList( + List positiveMatchFields = List.of( fieldWithPath("").description("Classes and methods with conditions that were matched."), fieldWithPath(".*.[].condition").description("Name of the condition."), fieldWithPath(".*.[].message").description("Details of why the condition was matched.")); - List negativeMatchFields = Arrays.asList( + List negativeMatchFields = List.of( fieldWithPath("").description("Classes and methods with conditions that were not matched."), fieldWithPath(".*.notMatched").description("Conditions that were matched."), fieldWithPath(".*.notMatched.[].condition").description("Name of the condition."), @@ -104,7 +84,7 @@ ConditionsReportEndpoint autoConfigurationReportEndpoint(ConfigurableApplication ConditionEvaluationReport conditionEvaluationReport = ConditionEvaluationReport .get(context.getBeanFactory()); conditionEvaluationReport - .recordEvaluationCandidates(Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName())); + .recordEvaluationCandidates(List.of(PropertyPlaceholderAutoConfiguration.class.getName())); return new ConditionsReportEndpoint(context); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/FlywayEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/FlywayEndpointDocumentationTests.java index 154f0f217a40..591b40e72318 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/FlywayEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/FlywayEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.List; import javax.sql.DataSource; @@ -61,7 +60,7 @@ void flyway() throws Exception { } private List migrationFieldDescriptors() { - return Arrays.asList(fieldWithPath("checksum").description("Checksum of the migration, if any.").optional(), + return List.of(fieldWithPath("checksum").description("Checksum of the migration, if any.").optional(), fieldWithPath("description").description("Description of the migration, if any.").optional(), fieldWithPath("executionTime").description("Execution time in milliseconds of an applied migration.") .optional(), diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java index a001d6869910..cc6920b3bf36 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HealthEndpointDocumentationTests.java @@ -17,7 +17,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; import java.io.File; -import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -68,7 +67,7 @@ */ class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentationTests { - private static final List componentFields = Arrays.asList( + private static final List componentFields = List.of( fieldWithPath("status").description("Status of a specific part of the application"), subsectionWithPath("details").description("Details of the health of a specific part of the application.")); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HttpExchangesEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HttpExchangesEndpointDocumentationTests.java index 9f757f2af553..95a91984ce75 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HttpExchangesEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HttpExchangesEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -22,9 +22,9 @@ import java.time.Duration; import java.time.Instant; import java.time.ZoneId; -import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; +import java.util.List; import java.util.UUID; import org.junit.jupiter.api.Test; @@ -66,11 +66,11 @@ void httpExchanges() throws Exception { given(request.getUri()).willReturn(URI.create("https://api.example.com")); given(request.getMethod()).willReturn("GET"); given(request.getHeaders()) - .willReturn(Collections.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json"))); + .willReturn(Collections.singletonMap(HttpHeaders.ACCEPT, List.of("application/json"))); RecordableHttpResponse response = mock(RecordableHttpResponse.class); given(response.getStatus()).willReturn(200); given(response.getHeaders()) - .willReturn(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json"))); + .willReturn(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, List.of("application/json"))); Principal principal = mock(Principal.class); given(principal.getName()).willReturn("alice"); Instant instant = Instant.parse("2022-12-22T13:43:41.00Z"); @@ -78,7 +78,7 @@ void httpExchanges() throws Exception { Clock end = Clock.offset(start, Duration.ofMillis(23)); HttpExchange exchange = HttpExchange.start(start, request) .finish(end, response, () -> principal, () -> UUID.randomUUID().toString(), EnumSet.allOf(Include.class)); - given(this.repository.findAll()).willReturn(Arrays.asList(exchange)); + given(this.repository.findAll()).willReturn(List.of(exchange)); this.mockMvc.perform(get("/actuator/httpexchanges")) .andExpect(status().isOk()) .andDo(document("httpexchanges", responseFields( diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LiquibaseEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LiquibaseEndpointDocumentationTests.java index 50329c8f86aa..cd12c81c2ca9 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LiquibaseEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LiquibaseEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.List; import liquibase.changelog.ChangeSet.ExecType; @@ -59,7 +58,7 @@ void liquibase() throws Exception { } private List getChangeSetFieldDescriptors() { - return Arrays.asList(fieldWithPath("author").description("Author of the change set."), + return List.of(fieldWithPath("author").description("Author of the change set."), fieldWithPath("changeLog").description("Change log that contains the change set."), fieldWithPath("comments").description("Comments on the change set."), fieldWithPath("contexts").description("Contexts of the change set."), diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LoggersEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LoggersEndpointDocumentationTests.java index 33f90fbe7563..acc1b10a2169 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LoggersEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/LoggersEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; -import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.List; @@ -55,18 +54,14 @@ */ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTests { - private static final List levelFields = Arrays.asList( + private static final List levelFields = List.of( fieldWithPath("configuredLevel").description("Configured level of the logger, if any.").optional(), fieldWithPath("effectiveLevel").description("Effective level of the logger.")); - private static final List groupLevelFields; - - static { - groupLevelFields = Arrays - .asList(fieldWithPath("configuredLevel").description("Configured level of the logger group, if any.") - .type(JsonFieldType.STRING) - .optional(), fieldWithPath("members").description("Loggers that are part of this group")); - } + private static final List groupLevelFields = List + .of(fieldWithPath("configuredLevel").description("Configured level of the logger group, if any.") + .type(JsonFieldType.STRING) + .optional(), fieldWithPath("members").description("Loggers that are part of this group")); @MockBean private LoggingSystem loggingSystem; @@ -78,7 +73,7 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest void allLoggers() throws Exception { given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class)); given(this.loggingSystem.getLoggerConfigurations()) - .willReturn(Arrays.asList(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO), + .willReturn(List.of(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO), new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG))); this.mockMvc.perform(get("/actuator/loggers")) .andExpect(status().isOk()) @@ -164,7 +159,7 @@ LoggersEndpoint endpoint(LoggingSystem loggingSystem, LoggerGroups groups) { } private Map> getLoggerGroups() { - return Collections.singletonMap("test", Arrays.asList("test.member1", "test.member2")); + return Collections.singletonMap("test", List.of("test.member1", "test.member2")); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointReactiveDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointReactiveDocumentationTests.java index 79c673e81282..ea189c393f31 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointReactiveDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointReactiveDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -18,7 +18,6 @@ import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -81,7 +80,7 @@ void webTestClient(RestDocumentationContextProvider restDocumentation) { @Test void mappings() { - List requestMappingConditions = Arrays.asList( + List requestMappingConditions = List.of( requestMappingConditionField("").description("Details of the request mapping conditions.").optional(), requestMappingConditionField(".consumes").description("Details of the consumes condition"), requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."), @@ -101,7 +100,7 @@ void mappings() { requestMappingConditionField(".produces").description("Details of the produces condition."), requestMappingConditionField(".produces.[].mediaType").description("Produced media type."), requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated.")); - List handlerMethod = Arrays.asList( + List handlerMethod = List.of( fieldWithPath("*.[].details.handlerMethod").optional() .type(JsonFieldType.OBJECT) .description("Details of the method, if any, that will handle requests to this mapping."), @@ -111,13 +110,13 @@ void mappings() { .description("Name of the method."), fieldWithPath("*.[].details.handlerMethod.descriptor").type(JsonFieldType.STRING) .description("Descriptor of the method as specified in the Java Language Specification.")); - List handlerFunction = Arrays.asList( + List handlerFunction = List.of( fieldWithPath("*.[].details.handlerFunction").optional() .type(JsonFieldType.OBJECT) .description("Details of the function, if any, that will handle requests to this mapping."), fieldWithPath("*.[].details.handlerFunction.className").type(JsonFieldType.STRING) .description("Fully qualified name of the class of the function.")); - List dispatcherHandlerFields = new ArrayList<>(Arrays.asList( + List dispatcherHandlerFields = new ArrayList<>(List.of( fieldWithPath("*") .description("Dispatcher handler mappings, if any, keyed by dispatcher handler bean name."), fieldWithPath("*.[].details").optional() diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointServletDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointServletDocumentationTests.java index b6399c7c3d4d..b11040e97f84 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointServletDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/MappingsEndpointServletDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -18,7 +18,6 @@ import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -94,7 +93,7 @@ void mappings() { .optional() .type(JsonFieldType.OBJECT), parentIdField()); - List dispatcherServletFields = new ArrayList<>(Arrays.asList( + List dispatcherServletFields = new ArrayList<>(List.of( fieldWithPath("*") .description("Dispatcher servlet mappings, if any, keyed by dispatcher servlet bean name."), fieldWithPath("*.[].details").optional() @@ -102,7 +101,7 @@ void mappings() { .description("Additional implementation-specific details about the mapping. Optional."), fieldWithPath("*.[].handler").description("Handler for the mapping."), fieldWithPath("*.[].predicate").description("Predicate for the mapping."))); - List requestMappingConditions = Arrays.asList( + List requestMappingConditions = List.of( requestMappingConditionField("").description("Details of the request mapping conditions.").optional(), requestMappingConditionField(".consumes").description("Details of the consumes condition"), requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."), @@ -122,7 +121,7 @@ void mappings() { requestMappingConditionField(".produces").description("Details of the produces condition."), requestMappingConditionField(".produces.[].mediaType").description("Produced media type."), requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated.")); - List handlerMethod = Arrays.asList( + List handlerMethod = List.of( fieldWithPath("*.[].details.handlerMethod").optional() .type(JsonFieldType.OBJECT) .description("Details of the method, if any, that will handle requests to this mapping."), diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/QuartzEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/QuartzEndpointDocumentationTests.java index 63093af47b98..fd51daf5d113 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/QuartzEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/QuartzEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -130,10 +130,10 @@ class QuartzEndpointDocumentationTests extends MockMvcEndpointDocumentationTests .withInterval(1, IntervalUnit.HOUR)) .build(); - private static final List triggerSummary = Arrays.asList(previousFireTime(""), nextFireTime(""), + private static final List triggerSummary = List.of(previousFireTime(""), nextFireTime(""), priority("")); - private static final List cronTriggerSummary = Arrays.asList( + private static final List cronTriggerSummary = List.of( fieldWithPath("expression").description("Cron expression to use."), fieldWithPath("timeZone").type(JsonFieldType.STRING) .optional() @@ -158,8 +158,8 @@ class QuartzEndpointDocumentationTests extends MockMvcEndpointDocumentationTests fieldWithPath("timeZone").type(JsonFieldType.STRING) .description("Time zone within which time calculations will be performed, if any.")); - private static final List customTriggerSummary = Collections.singletonList( - fieldWithPath("trigger").description("A toString representation of the custom trigger instance.")); + private static final List customTriggerSummary = List + .of(fieldWithPath("trigger").description("A toString representation of the custom trigger instance.")); private static final FieldDescriptor[] commonCronDetails = new FieldDescriptor[] { fieldWithPath("group").description("Name of the group."), @@ -280,7 +280,7 @@ void quartzJob() throws Exception { setPreviousNextFireTime(secondTrigger, "2020-12-04T03:00:00Z", "2020-12-04T12:00:00Z"); mockTriggers(firstTrigger, secondTrigger); given(this.scheduler.getTriggersOfJob(jobOne.getKey())) - .willAnswer((invocation) -> Arrays.asList(firstTrigger, secondTrigger)); + .willAnswer((invocation) -> List.of(firstTrigger, secondTrigger)); this.mockMvc.perform(get("/actuator/quartz/jobs/samples/jobOne")) .andExpect(status().isOk()) .andDo(document("quartz/job-details", responseFields( @@ -398,7 +398,7 @@ void quartzTriggerCustom() throws Exception { .andWithPrefix("custom.", customTriggerSummary))); } - private T setupTriggerDetails(TriggerBuilder builder, TriggerState state) + private void setupTriggerDetails(TriggerBuilder builder, TriggerState state) throws SchedulerException { T trigger = builder.withIdentity("example", "samples") .withDescription("Example trigger") @@ -409,7 +409,6 @@ private T setupTriggerDetails(TriggerBuilder builder, Tri setPreviousNextFireTime(trigger, "2020-12-04T03:00:00Z", "2020-12-07T03:00:00Z"); given(this.scheduler.getTriggerState(trigger.getKey())).willReturn(state); mockTriggers(trigger); - return trigger; } private static FieldDescriptor startTime(String prefix) { @@ -481,7 +480,7 @@ private void mockTriggers(Trigger... triggers) throws SchedulerException { } } - private T setPreviousNextFireTime(T trigger, String previousFireTime, String nextFireTime) { + private void setPreviousNextFireTime(T trigger, String previousFireTime, String nextFireTime) { OperableTrigger operableTrigger = (OperableTrigger) trigger; if (previousFireTime != null) { operableTrigger.setPreviousFireTime(fromUtc(previousFireTime)); @@ -489,7 +488,6 @@ private T setPreviousNextFireTime(T trigger, String previous if (nextFireTime != null) { operableTrigger.setNextFireTime(fromUtc(nextFireTime)); } - return trigger; } private static Date fromUtc(String utcTime) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ScheduledTasksEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ScheduledTasksEndpointDocumentationTests.java index efcc258699f1..cd757aa6cd51 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ScheduledTasksEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ScheduledTasksEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -33,7 +33,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskHolder; -import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; @@ -73,8 +72,7 @@ void scheduledTasks() throws Exception { initialDelayWithPrefix("fixedRate.[]."), fieldWithPath("custom").description("Tasks with custom triggers, if any."), targetFieldWithPrefix("custom.[]."), - fieldWithPath("custom.[].trigger").description("Trigger for the task.")))) - .andDo(MockMvcResultHandlers.print()); + fieldWithPath("custom.[].trigger").description("Trigger for the task.")))); } private FieldDescriptor targetFieldWithPrefix(String prefix) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java index 0d43d8fa122d..c33020828cfd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java @@ -17,7 +17,6 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; import java.time.Instant; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,7 +64,7 @@ class SessionsEndpointDocumentationTests extends MockMvcEndpointDocumentationTes private static final Session sessionThree = createSession(Instant.now().minusSeconds(60 * 60 * 2), Instant.now().minusSeconds(12)); - private static final List sessionFields = Arrays.asList( + private static final List sessionFields = List.of( fieldWithPath("id").description("ID of the session."), fieldWithPath("attributeNames").description("Names of the attributes stored in the session."), fieldWithPath("creationTime").description("Timestamp of when the session was created."), diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ShutdownEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ShutdownEndpointDocumentationTests.java index 033312870bff..36e5d3fdbf69 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ShutdownEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/ShutdownEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -23,7 +23,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.core.env.Environment; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -51,7 +50,7 @@ void shutdown() throws Exception { static class TestConfiguration { @Bean - ShutdownEndpoint endpoint(Environment environment) { + ShutdownEndpoint endpoint() { ShutdownEndpoint endpoint = new ShutdownEndpoint(); endpoint.setApplicationContext(new AnnotationConfigApplicationContext()); return endpoint; From 570602297f0e9abe46b7439ee7b19ed7017a2cd6 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Sun, 4 Feb 2024 15:07:31 +0100 Subject: [PATCH 029/182] Upgrade to JsonPath 2.9.0 Closes gh-39328 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c6eba6099322..a1ab09cc8509 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -693,7 +693,7 @@ bom { ] } } - library("Json Path", "2.8.0") { + library("Json Path", "2.9.0") { group("com.jayway.jsonpath") { modules = [ "json-path", From 149fb7effac0ef75d7f2f1a72bed9962563335ef Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 6 Feb 2024 11:16:22 +0100 Subject: [PATCH 030/182] Upgrade to Gradle 7.6.4 Closes gh-39404 --- gradle/wrapper/gradle-wrapper.jar | Bin 61624 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 29 +++++++++++++---------- gradlew.bat | 20 ++++++++-------- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index afba109285af78dbd2a1d187e33ac4f87c76e392..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 61624 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�Zy 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b1624c473c42..3e593191a337 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d65c8..1aa94a426907 100755 --- a/gradlew +++ b/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From be851aaee0a99ea9cfb64698b0831b267883f963 Mon Sep 17 00:00:00 2001 From: Ramil Sayetov Date: Tue, 6 Feb 2024 13:31:36 +0300 Subject: [PATCH 031/182] Fix awaitility link See gh-39415 --- .../spring-boot-docs/src/docs/asciidoc/features/testing.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index 24bcf0d1ee44..7e24391e1375 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -41,7 +41,7 @@ The `spring-boot-starter-test` "`Starter`" (in the `test` `scope`) contains the * https://site.mockito.org/[Mockito]: A Java mocking framework. * https://github.com/skyscreamer/JSONassert[JSONassert]: An assertion library for JSON. * https://github.com/jayway/JsonPath[JsonPath]: XPath for JSON. -* https://https://github.com/awaitility/awaitility[Awaitility]: A library for testing asynchronous systems. +* https://github.com/awaitility/awaitility[Awaitility]: A library for testing asynchronous systems. We generally find these common libraries to be useful when writing tests. If these libraries do not suit your needs, you can add additional test dependencies of your own. From 0abd9db439ec74536c087eebbc02f7817121e2c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:13:18 +0000 Subject: [PATCH 032/182] Bump gradle/gradle-build-action from 2.12.0 to 3.0.0 Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2.12.0 to 3.0.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/a8f75513eafdebd8141bd1cd4e30fcd194af8dfa...3b1b3b9a2104c2b47fbae53f3938079c00c9bb87) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] See gh-39407 --- .github/workflows/build-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 94f00d2050f3..305832c50911 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -23,7 +23,7 @@ jobs: uses: gradle/wrapper-validation-action@v1 - name: Set up Gradle - uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa + uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 - name: Build env: From bc7ef7205e3def7bc0023fa151ce9e044e57141a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:01:36 +0000 Subject: [PATCH 033/182] Bump gradle/wrapper-validation-action from 1 to 2 Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 1 to 2. - [Release notes](https://github.com/gradle/wrapper-validation-action/releases) - [Commits](https://github.com/gradle/wrapper-validation-action/compare/v1...v2) --- updated-dependencies: - dependency-name: gradle/wrapper-validation-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] See gh-39406 --- .github/workflows/build-pull-request.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 305832c50911..be7a584afb34 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/wrapper-validation-action@v2 - name: Set up Gradle uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index c87c892efbf0..cf2c086a063c 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -10,4 +10,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v1 + - uses: gradle/wrapper-validation-action@v2 From c22c5b62bb1a10299a7d40b10847f6aef1c3c6e9 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 6 Feb 2024 13:03:37 +0100 Subject: [PATCH 034/182] Polish "Bump gradle/wrapper-validation-action from 1 to 2" See gh-39406 --- .github/workflows/build-pull-request.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index be7a584afb34..6a8d68f0cc48 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v2 + uses: gradle/wrapper-validation-action@27152f6fa06a6b8062ef7195c795692e51fc2c81 - name: Set up Gradle uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index cf2c086a063c..c4c588261113 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -10,4 +10,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - uses: gradle/wrapper-validation-action@27152f6fa06a6b8062ef7195c795692e51fc2c81 From b25d52c8963d9f31eb0931c2887491bd0331946a Mon Sep 17 00:00:00 2001 From: lukasdooo Date: Sat, 3 Feb 2024 21:37:06 +0100 Subject: [PATCH 035/182] Update the Debugging Documentation of the Spring Boot Maven Plugin See gh-39392 --- .../docs/asciidoc/using/running-your-application.adoc | 2 +- .../src/docs/asciidoc/running.adoc | 4 ++-- .../src/docs/maven/running/debug-pom.xml | 2 +- .../springframework/boot/maven/RunArgumentsTests.java | 9 ++++----- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/using/running-your-application.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/using/running-your-application.adoc index 639d1dd637c9..51dc6ef81c08 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/using/running-your-application.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/using/running-your-application.adoc @@ -40,7 +40,7 @@ Doing so lets you attach a debugger to your packaged application, as shown in th [source,shell,indent=0,subs="verbatim"] ---- - $ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \ + $ java -agentlib:jdwp=server=y,transport=dt_socket,address=8000,suspend=n \ -jar target/myapplication-0.0.1-SNAPSHOT.jar ---- diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc index a1f877c626b2..7c1c5dd3b2a9 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc @@ -79,11 +79,11 @@ The following configuration suspend the process until a debugger has joined on p include::../maven/running/debug-pom.xml[tags=debug] ---- -These arguments can be specified on the command line as well, make sure to wrap that properly, that is: +These arguments can be specified on the command line as well: [indent=0] ---- - $ mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" + $ mvn spring-boot:run -Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 ---- diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/running/debug-pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/running/debug-pom.xml index 08db158eb8bf..b81d99214ffe 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/running/debug-pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/running/debug-pom.xml @@ -8,7 +8,7 @@ spring-boot-maven-plugin - -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 + -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java index 714d9b01c14c..e3b4d1d0c1e2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java @@ -63,11 +63,10 @@ void parseEmpty() { } @Test - void parseDebugFlags() { - String[] args = parseArgs("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"); - assertThat(args).hasSize(2); - assertThat(args[0]).isEqualTo("-Xdebug"); - assertThat(args[1]).isEqualTo("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"); + void parseDebugFlag() { + String[] args = parseArgs("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"); + assertThat(args).hasSize(1); + assertThat(args[0]).isEqualTo("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"); } @Test From 8fd28d9ece910bf48632b37af81c580e75a02a30 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 6 Feb 2024 13:07:55 +0100 Subject: [PATCH 036/182] Polish "Update the Debugging Documentation of the Spring Boot Maven Plugin" See gh-39392 --- .../spring-boot-maven-plugin/src/docs/asciidoc/running.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc index 7c1c5dd3b2a9..9e678319d8b0 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/running.adoc @@ -83,7 +83,7 @@ These arguments can be specified on the command line as well: [indent=0] ---- - $ mvn spring-boot:run -Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 + $ mvn spring-boot:run -Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 ---- From 41ed4d6cf4c5e316f236c99ce59cf7ddfa48ee89 Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Sat, 3 Feb 2024 00:29:45 -0600 Subject: [PATCH 037/182] Remove use of Pulsar ObjectMapperFactory This commit removes the use of the Pulsar ObjectMapperFactory when converting the authentication config props map to a JSON string. The Pulsar factory operates on a shaded returned value of Jackson ObjectMapper which may not exist when users are using the non-shaded version of the Pulsar client lib. See https://github.com/spring-projects/spring-pulsar/issues/562 See gh-39389 --- .../boot/autoconfigure/pulsar/PulsarPropertiesMapper.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java index ed9411512eb0..7b76c555022b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.apache.pulsar.client.admin.PulsarAdminBuilder; import org.apache.pulsar.client.api.ClientBuilder; @@ -30,7 +31,6 @@ import org.apache.pulsar.client.api.ProducerBuilder; import org.apache.pulsar.client.api.PulsarClientException.UnsupportedAuthenticationException; import org.apache.pulsar.client.api.ReaderBuilder; -import org.apache.pulsar.common.util.ObjectMapperFactory; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.pulsar.listener.PulsarContainerProperties; @@ -87,7 +87,10 @@ private void customizeAuthentication(AuthenticationConsumer authentication, private String getAuthenticationParamsJson(Map params) { Map sortedParams = new TreeMap<>(params); try { - return ObjectMapperFactory.create().writeValueAsString(sortedParams); + return sortedParams.entrySet() + .stream() + .map((e) -> "\"%s\":\"%s\"".formatted(e.getKey(), e.getValue())) + .collect(Collectors.joining(",", "{", "}")); } catch (Exception ex) { throw new IllegalStateException("Could not convert auth parameters to encoded string", ex); From 5f680ccac0e0afd0a7dc6039c9ea74553dfb48d3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 6 Feb 2024 11:37:40 +0000 Subject: [PATCH 038/182] Revert "Stop managing version of commons-compress where it isn't needed" This reverts commit 2b85cb03566b88d616fa51d970be6425c4d454d1. See gh-39367 --- gradle.properties | 1 - spring-boot-project/spring-boot-parent/build.gradle | 7 +++++++ .../spring-boot-buildpack-platform/build.gradle | 2 +- .../spring-boot-gradle-plugin/build.gradle | 2 +- .../spring-boot-loader-tools/build.gradle | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 718ab5b766f2..4a739e43a364 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,6 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 assertjVersion=3.24.2 commonsCodecVersion=1.15 -commonsCompressVersion=1.21 hamcrestVersion=2.2 jacksonVersion=2.15.3 junitJupiterVersion=5.9.3 diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 2e8a3a3315e0..48b8d88b3b6f 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -34,6 +34,13 @@ bom { ] } } + library("Commons Compress", "1.21") { + group("org.apache.commons") { + modules = [ + "commons-compress" + ] + } + } library("Commons FileUpload", "1.5") { group("commons-fileupload") { modules = [ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle index 0e448630278b..d6b393c6819e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle @@ -22,7 +22,7 @@ dependencies { api("com.fasterxml.jackson.core:jackson-databind") api("com.fasterxml.jackson.module:jackson-module-parameter-names") api("net.java.dev.jna:jna-platform") - api("org.apache.commons:commons-compress:$commonsCompressVersion") + api("org.apache.commons:commons-compress") api("org.apache.httpcomponents.client5:httpclient5") api("org.springframework:spring-core") api("org.tomlj:tomlj:1.0.0") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle index 6abef56e5b02..48e174123a43 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle @@ -34,7 +34,7 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools")) implementation("io.spring.gradle:dependency-management-plugin") - implementation("org.apache.commons:commons-compress:$commonsCompressVersion") + implementation("org.apache.commons:commons-compress") implementation("org.springframework:spring-core") optional("org.graalvm.buildtools:native-gradle-plugin") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle index 738f53333820..c6b187317071 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle @@ -20,7 +20,7 @@ configurations { } dependencies { - api("org.apache.commons:commons-compress:$commonsCompressVersion") + api("org.apache.commons:commons-compress") api("org.springframework:spring-core") compileOnly("ch.qos.logback:logback-classic") From 5ae533a00d853ed4b9a7683fa582f99cf01c53c7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 6 Feb 2024 15:08:15 +0000 Subject: [PATCH 039/182] Minimize scope of version management for commons-compress See gh-39368 --- gradle.properties | 1 + spring-boot-project/spring-boot-parent/build.gradle | 7 ------- .../spring-boot-buildpack-platform/build.gradle | 13 ++++++++++++- .../spring-boot-gradle-plugin/build.gradle | 13 ++++++++++++- .../spring-boot-gradle-test-support/build.gradle | 2 +- .../spring-boot-loader-tools/build.gradle | 8 +++++++- .../boot/image/assertions/ImageAssert.java | 8 ++++---- 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/gradle.properties b/gradle.properties index 22d7baf4a925..28236114ec4a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 assertjVersion=3.24.2 commonsCodecVersion=1.16.0 +commonsCompressVersion=1.21 hamcrestVersion=2.2 jacksonVersion=2.15.3 junitJupiterVersion=5.10.1 diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 52b0104b582e..8a2bf315f0ee 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -34,13 +34,6 @@ bom { ] } } - library("Commons Compress", "1.21") { - group("org.apache.commons") { - modules = [ - "commons-compress" - ] - } - } library("Commons FileUpload", "1.5") { group("commons-fileupload") { modules = [ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle index b99a4c61c3e4..f3886f7b8471 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/build.gradle @@ -19,6 +19,17 @@ configurations.all { if (dependency.requested.group.equals("org.springframework")) { dependency.useVersion("6.0.10") } + // We manage the version of commons-compress here rather than + // in spring-boot-parent to minimize conflicts with Testcontainers + if (dependency.requested.group.equals("org.apache.commons") + && dependency.requested.name.equals("commons-compress")) { + dependency.useVersion("$commonsCompressVersion") + } + // Downgrade Testcontainers for compatibility with the managed + // version of Commons Compress. + if (dependency.requested.group.equals("org.testcontainers")) { + dependency.useVersion("1.19.3") + } } } } @@ -27,7 +38,7 @@ dependencies { api("com.fasterxml.jackson.core:jackson-databind") api("com.fasterxml.jackson.module:jackson-module-parameter-names") api("net.java.dev.jna:jna-platform") - api("org.apache.commons:commons-compress") + api("org.apache.commons:commons-compress:$commonsCompressVersion") api("org.apache.httpcomponents.client5:httpclient5") api("org.springframework:spring-core") api("org.tomlj:tomlj:1.0.0") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle index 35cd303513d7..36a2c3b8f6e1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/build.gradle @@ -28,6 +28,17 @@ configurations { if (dependency.requested.group.equals("org.springframework")) { dependency.useVersion("6.0.10") } + // We manage the version of commons-compress here rather than + // in spring-boot-parent to minimize conflicts with Testcontainers + if (dependency.requested.group.equals("org.apache.commons") + && dependency.requested.name.equals("commons-compress")) { + dependency.useVersion("$commonsCompressVersion") + } + // Downgrade Testcontainers for compatibility with the managed + // version of Commons Compress. + if (dependency.requested.group.equals("org.testcontainers")) { + dependency.useVersion("1.19.3") + } } } } @@ -39,7 +50,7 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-buildpack-platform")) implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-loader-tools")) implementation("io.spring.gradle:dependency-management-plugin") - implementation("org.apache.commons:commons-compress") + implementation("org.apache.commons:commons-compress:$commonsCompressVersion") implementation("org.springframework:spring-core") optional("org.graalvm.buildtools:native-gradle-plugin") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/build.gradle index d3df269b1b2c..c71fca96a3b8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlinVersion") implementation("org.jetbrains.kotlin:kotlin-compiler-runner:$kotlinVersion") implementation("org.jetbrains.kotlin:kotlin-daemon-client:$kotlinVersion") - implementation("org.apache.commons:commons-compress") + implementation("org.apache.commons:commons-compress:$commonsCompressVersion") implementation("org.assertj:assertj-core") } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle index f7968f659d51..7c2053406537 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/build.gradle @@ -29,13 +29,19 @@ configurations { if (dependency.requested.group.equals("org.springframework")) { dependency.useVersion("6.0.10") } + // We manage the version of commons-compress here rather than + // in spring-boot-parent to minimize conflicts with Testcontainers + if (dependency.requested.group.equals("org.apache.commons") + && dependency.requested.name.equals("commons-compress")) { + dependency.useVersion("$commonsCompressVersion") + } } } } } dependencies { - api("org.apache.commons:commons-compress") + api("org.apache.commons:commons-compress:$commonsCompressVersion") api("org.springframework:spring-core") compileOnly("ch.qos.logback:logback-classic") diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java index ce326c1702ba..fc5f9509412b 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java @@ -80,12 +80,12 @@ public ListAssert entries() { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { if (!entry.isDirectory()) { entryNames.add(entry.getName().replaceFirst("^/workspace/", "")); } - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } } @@ -101,7 +101,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextTarEntry(); + TarArchiveEntry entry = in.getNextEntry(); while (entry != null) { if (entry.getName().equals(name)) { ByteArrayOutputStream entryOut = new ByteArrayOutputStream(); @@ -109,7 +109,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { assertConsumer.accept(new JsonContentAssert(LayerContentAssert.class, entryOut.toString())); return; } - entry = in.getNextTarEntry(); + entry = in.getNextEntry(); } } failWithMessage("Expected JSON entry '%s' in layer with digest '%s'", name, this.actual.getId()); From 2374e7d4eb3c4bbfcf89becda7c90c722e77c4b2 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 6 Feb 2024 15:25:39 -0600 Subject: [PATCH 040/182] Fix invalid request handling for WebFlux actuator endpoints Fixes gh-39236 --- ...AbstractWebFluxEndpointHandlerMapping.java | 25 +++++++++- .../AbstractWebEndpointIntegrationTests.java | 46 +++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java index 3621a5b94a52..3cb0cf56e0a6 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java @@ -83,6 +83,7 @@ * @author Madhura Bhave * @author Phillip Webb * @author Brian Clozel + * @author Scott Frederick * @since 2.0.0 */ @ImportRuntimeHints(AbstractWebFluxEndpointHandlerMappingRuntimeHints.class) @@ -260,6 +261,26 @@ public Object invoke(InvocationContext context) { } + protected static final class ExceptionCapturingInvoker implements OperationInvoker { + + private final OperationInvoker invoker; + + public ExceptionCapturingInvoker(OperationInvoker invoker) { + this.invoker = invoker; + } + + @Override + public Object invoke(InvocationContext context) { + try { + return this.invoker.invoke(context); + } + catch (Exception ex) { + return Mono.error(ex); + } + } + + } + /** * Reactive handler providing actuator links at the root endpoint. */ @@ -303,9 +324,9 @@ private ReactiveWebOperationAdapter(WebOperation operation) { private OperationInvoker getInvoker(WebOperation operation) { OperationInvoker invoker = operation::invoke; if (operation.isBlocking()) { - invoker = new ElasticSchedulerInvoker(invoker); + return new ElasticSchedulerInvoker(invoker); } - return invoker; + return new ExceptionCapturingInvoker(invoker); } private Supplier> getSecurityContextSupplier() { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/AbstractWebEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/AbstractWebEndpointIntegrationTests.java index 23f370bac339..cc2286270fd3 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/AbstractWebEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/annotation/AbstractWebEndpointIntegrationTests.java @@ -226,6 +226,31 @@ void readOperationWithSingleQueryParameters() { .isEqualTo("1 2")); } + @Test + void readOperationWithQueryParametersMissing() { + load(QueryEndpointConfiguration.class, + (client) -> client.get().uri("/query").exchange().expectStatus().isBadRequest()); + } + + @Test + void reactiveReadOperationWithSingleQueryParameters() { + load(ReactiveQueryEndpointConfiguration.class, + (client) -> client.get() + .uri("/query?param=test") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .jsonPath("query") + .isEqualTo("test")); + } + + @Test + void reactiveReadOperationWithQueryParametersMissing() { + load(ReactiveQueryEndpointConfiguration.class, + (client) -> client.get().uri("/query").exchange().expectStatus().isBadRequest()); + } + @Test void readOperationWithSingleQueryParametersAndMultipleValues() { load(QueryEndpointConfiguration.class, @@ -732,6 +757,17 @@ QueryWithListEndpoint queryEndpoint() { } + @Configuration(proxyBeanMethods = false) + @Import(BaseConfiguration.class) + static class ReactiveQueryEndpointConfiguration { + + @Bean + ReactiveQueryEndpoint reactiveQueryEndpoint() { + return new ReactiveQueryEndpoint(); + } + + } + @Configuration(proxyBeanMethods = false) @Import(BaseConfiguration.class) static class VoidWriteResponseEndpointConfiguration { @@ -974,6 +1010,16 @@ Map queryWithParameterList(String one, List two) { } + @Endpoint(id = "query") + static class ReactiveQueryEndpoint { + + @ReadOperation + Mono> query(String param) { + return Mono.just(Collections.singletonMap("query", param)); + } + + } + @Endpoint(id = "voidwrite") static class VoidWriteResponseEndpoint { From d616568324f85fda58cb8dca1355ea0f62b14257 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 7 Feb 2024 15:43:35 -0600 Subject: [PATCH 041/182] Upgrade CI images to ubuntu:jammy-20240125 Closes gh-39426 --- ci/images/ci-image-jdk21/Dockerfile | 2 +- ci/images/ci-image/Dockerfile | 2 +- .../intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile | 4 ++-- .../src/intTest/resources/conf/oracle-jdk-17/Dockerfile | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/images/ci-image-jdk21/Dockerfile b/ci/images/ci-image-jdk21/Dockerfile index c13dea362bf7..777a94f0a731 100644 --- a/ci/images/ci-image-jdk21/Dockerfile +++ b/ci/images/ci-image-jdk21/Dockerfile @@ -1,5 +1,5 @@ ARG DOCKER_PROXY_CACHE= -FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240111 +FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240125 ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh diff --git a/ci/images/ci-image/Dockerfile b/ci/images/ci-image/Dockerfile index f660b06a0426..581c18b9de00 100644 --- a/ci/images/ci-image/Dockerfile +++ b/ci/images/ci-image/Dockerfile @@ -1,5 +1,5 @@ ARG DOCKER_PROXY_CACHE= -FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240111 +FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240125 ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile index 0f7782c811f0..3ed174cd2605 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile @@ -1,10 +1,10 @@ -FROM ubuntu:jammy-20240111 as prepare +FROM ubuntu:jammy-20240125 as prepare COPY downloads/* /opt/download/ RUN mkdir -p /opt/jdk && \ cd /opt/jdk && \ tar xzf /opt/download/* --strip-components=1 -FROM ubuntu:jammy-20240111 +FROM ubuntu:jammy-20240125 RUN apt-get update && apt-get install -y software-properties-common curl COPY --from=prepare /opt/jdk /opt/jdk ENV JAVA_HOME /opt/jdk diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile index f27488f00f85..2141eaa09fd6 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile @@ -1,10 +1,10 @@ -FROM ubuntu:jammy-20240111 as prepare +FROM ubuntu:jammy-20240125 as prepare COPY downloads/* /opt/download/ RUN mkdir -p /opt/jdk && \ cd /opt/jdk && \ tar xzf /opt/download/* --strip-components=1 -FROM ubuntu:jammy-20240111 +FROM ubuntu:jammy-20240125 COPY --from=prepare /opt/jdk /opt/jdk ENV JAVA_HOME /opt/jdk ENV PATH $JAVA_HOME/bin:$PATH From a60d42353f0e842e48bac6eac354af75295652de Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 7 Feb 2024 15:47:24 -0600 Subject: [PATCH 042/182] Upgrade CI to Docker 25.0.3 Closes gh-39442 --- ci/images/get-docker-url.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/images/get-docker-url.sh b/ci/images/get-docker-url.sh index 1e4971b85383..cf11be941203 100755 --- a/ci/images/get-docker-url.sh +++ b/ci/images/get-docker-url.sh @@ -1,5 +1,5 @@ #!/bin/bash set -e -version="25.0.1" +version="25.0.3" echo "https://download.docker.com/linux/static/stable/x86_64/docker-$version.tgz"; From 1fcddffa44370159d82ffd80644cbc1bb91f9b65 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 7 Feb 2024 16:27:28 -0600 Subject: [PATCH 043/182] Authenticate to GitHub when querying issues in CI scripts Closes gh-39446 --- ci/scripts/detect-docker-updates.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/scripts/detect-docker-updates.sh b/ci/scripts/detect-docker-updates.sh index 3d15719b56ec..d517dd8fa2eb 100755 --- a/ci/scripts/detect-docker-updates.sh +++ b/ci/scripts/detect-docker-updates.sh @@ -8,8 +8,8 @@ if [[ $latest_version =~ (beta|rc) ]]; then fi title_prefix="Upgrade CI to Docker" -milestone_number=$( curl -s https://api.github.com/repos/${GITHUB_ORGANIZATION}/${GITHUB_REPO}/milestones\?state\=open | jq -c --arg MILESTONE "$MILESTONE" '.[] | select(.title==$MILESTONE)' | jq -r '.number') -existing_upgrade_issues=$( curl -s https://api.github.com/repos/${GITHUB_ORGANIZATION}/${GITHUB_REPO}/issues\?labels\=type:%20task\&state\=open\&creator\=spring-builds\&milestone\=${milestone_number} | jq -c --arg TITLE_PREFIX "$title_prefix" '.[] | select(.title | startswith($TITLE_PREFIX))' ) +milestone_number=$( curl -u ${GITHUB_USERNAME}:${GITHUB_PASSWORD} -s https://api.github.com/repos/${GITHUB_ORGANIZATION}/${GITHUB_REPO}/milestones\?state\=open | jq -c --arg MILESTONE "$MILESTONE" '.[] | select(.title==$MILESTONE)' | jq -r '.number') +existing_upgrade_issues=$( curl -u ${GITHUB_USERNAME}:${GITHUB_PASSWORD} -s https://api.github.com/repos/${GITHUB_ORGANIZATION}/${GITHUB_REPO}/issues\?labels\=type:%20task\&state\=open\&creator\=spring-builds\&milestone\=${milestone_number} | jq -c --arg TITLE_PREFIX "$title_prefix" '.[] | select(.title | startswith($TITLE_PREFIX))' ) latest="https://download.docker.com/linux/static/stable/x86_64/docker-$latest_version.tgz" current=$( git-repo/ci/images/get-docker-url.sh ) From 67ba829d9eb0539a3365beef366079270ecd533b Mon Sep 17 00:00:00 2001 From: Amrit Date: Wed, 7 Feb 2024 23:22:26 +0530 Subject: [PATCH 044/182] Fix typo in TestcontainersPropertySource assertion See gh-39440 --- .../properties/TestcontainersPropertySource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java index 03cc0932292a..57a3aa83547c 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -86,7 +86,7 @@ private static DynamicPropertyRegistry attach(ConfigurableEnvironment environmen return attach(environment); } Assert.state(propertySource instanceof TestcontainersPropertySource, - "Incorrect DynamicValuesPropertySource type registered"); + "Incorrect TestcontainersPropertySource type registered"); return ((TestcontainersPropertySource) propertySource).registry; } From d941f62a7329ec59f621515ff26a8e20ebe9354c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:04 +0000 Subject: [PATCH 045/182] Start building against Micrometer 1.11.9 snapshots See gh-39454 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a1ab09cc8509..3e3cad008c26 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -975,7 +975,7 @@ bom { ] } } - library("Micrometer", "1.11.8") { + library("Micrometer", "1.11.9-SNAPSHOT") { considerSnapshots() group("io.micrometer") { modules = [ From 5b0b327acb64f2a3fd4269a76b3974a6bfffaed9 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:08 +0000 Subject: [PATCH 046/182] Start building against Micrometer Tracing 1.1.10 snapshots See gh-39455 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3e3cad008c26..e9490eb7dd68 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -988,7 +988,7 @@ bom { ] } } - library("Micrometer Tracing", "1.1.9") { + library("Micrometer Tracing", "1.1.10-SNAPSHOT") { considerSnapshots() calendarName = "Tracing" group("io.micrometer") { From 9bf17cca7f7497175e72a33509e596d24184793a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:13 +0000 Subject: [PATCH 047/182] Start building against Reactor Bom 2022.0.16 snapshots See gh-39456 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e9490eb7dd68..2e11894345e0 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1217,7 +1217,7 @@ bom { ] } } - library("Reactor Bom", "2022.0.15") { + library("Reactor Bom", "2022.0.16-SNAPSHOT") { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { From d402d0ecfd2b069ae7e6b56f8473f5d59b9bfbe4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:18 +0000 Subject: [PATCH 048/182] Start building against Spring AMQP 3.0.11 snapshots See gh-39457 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 2e11894345e0..d3ab68f72a24 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1382,7 +1382,7 @@ bom { ] } } - library("Spring AMQP", "3.0.10") { + library("Spring AMQP", "3.0.11-SNAPSHOT") { considerSnapshots() group("org.springframework.amqp") { imports = [ From 559aad31758856d3ed040355f2918abbbf3957cd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:22 +0000 Subject: [PATCH 049/182] Start building against Spring Authorization Server 1.1.5 snapshots See gh-39458 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d3ab68f72a24..516c70e8313c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1390,7 +1390,7 @@ bom { ] } } - library("Spring Authorization Server", "1.1.4") { + library("Spring Authorization Server", "1.1.5-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { modules = [ From 50d66a9844f32e0f13257b64cba7f2d89285cafd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:27 +0000 Subject: [PATCH 050/182] Start building against Spring Batch 5.0.5 snapshots See gh-39459 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 516c70e8313c..371562aba184 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1398,7 +1398,7 @@ bom { ] } } - library("Spring Batch", "5.0.4") { + library("Spring Batch", "5.0.5-SNAPSHOT") { considerSnapshots() group("org.springframework.batch") { imports = [ From 7efdf0a428a41f6a2273758398e52a526f2e35ad Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:32 +0000 Subject: [PATCH 051/182] Start building against Spring Data Bom 2023.0.9 snapshots See gh-39460 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 371562aba184..3be6f693ec20 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1406,7 +1406,7 @@ bom { ] } } - library("Spring Data Bom", "2023.0.8") { + library("Spring Data Bom", "2023.0.9-SNAPSHOT") { considerSnapshots() calendarName = "Spring Data Release" group("org.springframework.data") { From a200dfe15785fedc4375742601ed58106178d5f1 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:37 +0000 Subject: [PATCH 052/182] Start building against Spring Framework 6.0.17 snapshots See gh-39461 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4a739e43a364..7bf2056e2de1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ junitJupiterVersion=5.9.3 kotlinVersion=1.8.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 -springFrameworkVersion=6.0.16 +springFrameworkVersion=6.0.17-SNAPSHOT tomcatVersion=10.1.18 kotlin.stdlib.default.dependency=false From af3ffb209ca6c67cc689f60743cf91328f1ab354 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:41 +0000 Subject: [PATCH 053/182] Start building against Spring GraphQL 1.2.5 snapshots See gh-39462 Co-authored-by: Brian Clozel --- ...raphQlWebMvcSecurityAutoConfigurationTests.java | 12 +++--------- .../GraphQlWebMvcAutoConfigurationTests.java | 14 ++++---------- .../spring-boot-dependencies/build.gradle | 2 +- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java index a7deb9a3afdb..45ea3fdcc818 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-2024 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. @@ -46,14 +46,12 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -84,8 +82,7 @@ void contributesSecurityComponents() { void anonymousUserShouldBeUnauthorized() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author }}"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("data.bookById.name").doesNotExist()) @@ -97,10 +94,7 @@ void anonymousUserShouldBeUnauthorized() { void authenticatedUserShouldGetData() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author }}"; - MvcResult result = mockMvc - .perform(post("/graphql").content("{\"query\": \"" + query + "\"}").with(user("rob"))) - .andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}").with(user("rob"))) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("data.bookById.name").value("GraphQL for beginners")) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java index e99c778746a8..a1e03f3f73db 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -43,12 +43,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.servlet.function.RouterFunction; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -84,8 +82,7 @@ void shouldContributeDefaultBeans() { void simpleQueryShouldWork() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_GRAPHQL_RESPONSE)) .andExpect(jsonPath("data.bookById.name").value("GraphQL for beginners")); @@ -116,8 +113,7 @@ void shouldRejectQueryWithInvalidJson() { void shouldConfigureWebInterceptors() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(header().string("X-Custom-Header", "42")); }); @@ -148,12 +144,10 @@ void shouldSupportCors() { testWith((mockMvc) -> { String query = "{" + " bookById(id: \\\"book-1\\\"){ " + " id" + " name" + " pageCount" + " author" + " }" + "}"; - MvcResult result = mockMvc + mockMvc .perform(post("/graphql").header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST") .header(HttpHeaders.ORIGIN, "https://example.com") .content("{\"query\": \"" + query + "\"}")) - .andReturn(); - mockMvc.perform(asyncDispatch(result)) .andExpect(status().isOk()) .andExpect(header().stringValues(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "https://example.com")) .andExpect(header().stringValues(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")); diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3be6f693ec20..9335242a32b4 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1424,7 +1424,7 @@ bom { ] } } - library("Spring GraphQL", "1.2.4") { + library("Spring GraphQL", "1.2.5-SNAPSHOT") { considerSnapshots() group("org.springframework.graphql") { modules = [ From 420789fc63b7739eaa8cbb4360428745018d54d2 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:46 +0000 Subject: [PATCH 054/182] Start building against Spring Integration 6.1.6 snapshots See gh-39463 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 9335242a32b4..5790f76cf588 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1441,7 +1441,7 @@ bom { ] } } - library("Spring Integration", "6.1.5") { + library("Spring Integration", "6.1.6-SNAPSHOT") { considerSnapshots() group("org.springframework.integration") { imports = [ From 5671a4e8c5221bc3c168aef93682b4140ceec07b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:50 +0000 Subject: [PATCH 055/182] Start building against Spring Kafka 3.0.14 snapshots See gh-39464 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 5790f76cf588..a40e0485ccdc 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1449,7 +1449,7 @@ bom { ] } } - library("Spring Kafka", "3.0.13") { + library("Spring Kafka", "3.0.14-SNAPSHOT") { considerSnapshots() group("org.springframework.kafka") { modules = [ From 097ff791d68ce4d4e9a05dd09e9915aec318e772 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:29:55 +0000 Subject: [PATCH 056/182] Start building against Spring LDAP 3.1.4 snapshots See gh-39465 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a40e0485ccdc..5ee0247241a7 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1458,7 +1458,7 @@ bom { ] } } - library("Spring LDAP", "3.1.3") { + library("Spring LDAP", "3.1.4-SNAPSHOT") { considerSnapshots() group("org.springframework.ldap") { modules = [ From e584ed3c6870d15cc4c0446fc2227be37600c6a6 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 8 Feb 2024 13:30:00 +0000 Subject: [PATCH 057/182] Start building against Spring Security 6.1.7 snapshots See gh-39466 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 5ee0247241a7..3b8a332102a9 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1485,7 +1485,7 @@ bom { ] } } - library("Spring Security", "6.1.6") { + library("Spring Security", "6.1.7-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { imports = [ From f26ab78ed789d0797a7dd2742a2cc88bc4eadf4e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:57:56 +0000 Subject: [PATCH 058/182] Start building against Micrometer 1.12.3 snapshots See gh-39474 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 9bc2ed236f20..cf39b7be4964 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -995,7 +995,7 @@ bom { ] } } - library("Micrometer", "1.12.2") { + library("Micrometer", "1.12.3-SNAPSHOT") { considerSnapshots() group("io.micrometer") { modules = [ From 3f02b632f8aeeec5b95c32c8841a51f56bdd7c93 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:01 +0000 Subject: [PATCH 059/182] Start building against Micrometer Tracing 1.2.3 snapshots See gh-39475 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index cf39b7be4964..25a5ac4eaea6 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1008,7 +1008,7 @@ bom { ] } } - library("Micrometer Tracing", "1.2.2") { + library("Micrometer Tracing", "1.2.3-SNAPSHOT") { considerSnapshots() calendarName = "Tracing" group("io.micrometer") { From 316151bbf57996abf937561e620b75a37d331df7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:05 +0000 Subject: [PATCH 060/182] Start building against Reactor Bom 2023.0.3 snapshots See gh-39476 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 25a5ac4eaea6..d3368ce0da29 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1327,7 +1327,7 @@ bom { ] } } - library("Reactor Bom", "2023.0.2") { + library("Reactor Bom", "2023.0.3-SNAPSHOT") { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { From 29659738ce85d84e8a9cf06c20e199b09bfbbc87 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:10 +0000 Subject: [PATCH 061/182] Start building against Spring AMQP 3.1.2 snapshots See gh-39477 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d3368ce0da29..d8afa04ea812 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1495,7 +1495,7 @@ bom { ] } } - library("Spring AMQP", "3.1.1") { + library("Spring AMQP", "3.1.2-SNAPSHOT") { considerSnapshots() group("org.springframework.amqp") { imports = [ From e90e4c51e7403157f0982ee5057e956b1c3cf349 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:15 +0000 Subject: [PATCH 062/182] Start building against Spring Authorization Server 1.2.2 snapshots See gh-39478 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d8afa04ea812..9ceaf00fa525 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1503,7 +1503,7 @@ bom { ] } } - library("Spring Authorization Server", "1.2.1") { + library("Spring Authorization Server", "1.2.2-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { modules = [ From f527e9a6fcb04e6946be94ae141160f91d69d87c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:19 +0000 Subject: [PATCH 063/182] Start building against Spring Batch 5.1.1 snapshots See gh-39479 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 9ceaf00fa525..edae1dc62abd 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1511,7 +1511,7 @@ bom { ] } } - library("Spring Batch", "5.1.0") { + library("Spring Batch", "5.1.1-SNAPSHOT") { considerSnapshots() group("org.springframework.batch") { imports = [ From c58406c7a5de0c2d7228305f8afca0ccb092eb04 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:24 +0000 Subject: [PATCH 064/182] Start building against Spring Data Bom 2023.1.3 snapshots See gh-39480 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index edae1dc62abd..32e85d92ff4a 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1519,7 +1519,7 @@ bom { ] } } - library("Spring Data Bom", "2023.1.2") { + library("Spring Data Bom", "2023.1.3-SNAPSHOT") { considerSnapshots() calendarName = "Spring Data Release" group("org.springframework.data") { From 4b37228cfaa5eaf638faeac306046839621e076c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:29 +0000 Subject: [PATCH 065/182] Start building against Spring Framework 6.1.4 snapshots See gh-39481 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 28236114ec4a..d1786b540b68 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ junitJupiterVersion=5.10.1 kotlinVersion=1.9.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 -springFrameworkVersion=6.1.3 +springFrameworkVersion=6.1.4-SNAPSHOT tomcatVersion=10.1.18 kotlin.stdlib.default.dependency=false From dada1378bd847ab29492827d26c206b054c413ba Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:34 +0000 Subject: [PATCH 066/182] Start building against Spring GraphQL 1.2.5 snapshots See gh-39482 --- ...raphQlWebMvcSecurityAutoConfigurationTests.java | 12 +++--------- .../GraphQlWebMvcAutoConfigurationTests.java | 14 ++++---------- .../spring-boot-dependencies/build.gradle | 2 +- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java index a7deb9a3afdb..45ea3fdcc818 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/security/GraphQlWebMvcSecurityAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-2024 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. @@ -46,14 +46,12 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.config.Customizer.withDefaults; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -84,8 +82,7 @@ void contributesSecurityComponents() { void anonymousUserShouldBeUnauthorized() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author }}"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("data.bookById.name").doesNotExist()) @@ -97,10 +94,7 @@ void anonymousUserShouldBeUnauthorized() { void authenticatedUserShouldGetData() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author }}"; - MvcResult result = mockMvc - .perform(post("/graphql").content("{\"query\": \"" + query + "\"}").with(user("rob"))) - .andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}").with(user("rob"))) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("data.bookById.name").value("GraphQL for beginners")) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java index 6df0fdff742a..cd082e39ac6b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -43,7 +43,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.function.RouterFunction; @@ -52,7 +51,6 @@ import org.springframework.web.socket.server.support.WebSocketHandlerMapping; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -88,8 +86,7 @@ void shouldContributeDefaultBeans() { void simpleQueryShouldWork() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_GRAPHQL_RESPONSE)) .andExpect(jsonPath("data.bookById.name").value("GraphQL for beginners")); @@ -120,8 +117,7 @@ void shouldRejectQueryWithInvalidJson() { void shouldConfigureWebInterceptors() { testWith((mockMvc) -> { String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }"; - MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn(); - mockMvc.perform(asyncDispatch(result)) + mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")) .andExpect(status().isOk()) .andExpect(header().string("X-Custom-Header", "42")); }); @@ -152,12 +148,10 @@ void shouldSupportCors() { testWith((mockMvc) -> { String query = "{" + " bookById(id: \\\"book-1\\\"){ " + " id" + " name" + " pageCount" + " author" + " }" + "}"; - MvcResult result = mockMvc + mockMvc .perform(post("/graphql").header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST") .header(HttpHeaders.ORIGIN, "https://example.com") .content("{\"query\": \"" + query + "\"}")) - .andReturn(); - mockMvc.perform(asyncDispatch(result)) .andExpect(status().isOk()) .andExpect(header().stringValues(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "https://example.com")) .andExpect(header().stringValues(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")); diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 32e85d92ff4a..e16409cb8337 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1537,7 +1537,7 @@ bom { ] } } - library("Spring GraphQL", "1.2.4") { + library("Spring GraphQL", "1.2.5-SNAPSHOT") { considerSnapshots() group("org.springframework.graphql") { modules = [ From 65a96b270d023f2f82f504d2d035ee644cdaeb05 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:38 +0000 Subject: [PATCH 067/182] Start building against Spring Integration 6.2.2 snapshots See gh-39483 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e16409cb8337..386bfb1f3663 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1554,7 +1554,7 @@ bom { ] } } - library("Spring Integration", "6.2.1") { + library("Spring Integration", "6.2.2-SNAPSHOT") { considerSnapshots() group("org.springframework.integration") { imports = [ From b1d841dab83e78870fa5ea1acf2956b7b5c759d8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:43 +0000 Subject: [PATCH 068/182] Start building against Spring Kafka 3.1.2 snapshots See gh-39484 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 386bfb1f3663..006bb194f6e3 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1562,7 +1562,7 @@ bom { ] } } - library("Spring Kafka", "3.1.1") { + library("Spring Kafka", "3.1.2-SNAPSHOT") { considerSnapshots() group("org.springframework.kafka") { modules = [ From 3ab24c06631aacbd2e3dafdc7ef6b5216dd52d63 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:48 +0000 Subject: [PATCH 069/182] Start building against Spring LDAP 3.2.2 snapshots See gh-39485 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 006bb194f6e3..76089d58cbe2 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1571,7 +1571,7 @@ bom { ] } } - library("Spring LDAP", "3.2.1") { + library("Spring LDAP", "3.2.2-SNAPSHOT") { considerSnapshots() group("org.springframework.ldap") { modules = [ From 54201108145d36b9928efd31c6c6c21bec4dab82 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:53 +0000 Subject: [PATCH 070/182] Start building against Spring Pulsar 1.0.3 snapshots See gh-39486 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 76089d58cbe2..efdd56d57225 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1582,7 +1582,7 @@ bom { ] } } - library("Spring Pulsar", "1.0.2") { + library("Spring Pulsar", "1.0.3-SNAPSHOT") { considerSnapshots() group("org.springframework.pulsar") { imports = [ From aa061696b1a825268fa713e824d1e63ff7aa25ad Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 09:58:57 +0000 Subject: [PATCH 071/182] Start building against Spring Security 6.2.2 snapshots See gh-39487 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index efdd56d57225..3a02e99f5d40 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1606,7 +1606,7 @@ bom { ] } } - library("Spring Security", "6.2.1") { + library("Spring Security", "6.2.2-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { imports = [ From c64b1d12f23d6496f965a710a656e5e5163967ad Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Sun, 11 Feb 2024 13:04:43 -0600 Subject: [PATCH 072/182] Ignore syft deprecation warnings in Paketo system tests Closes gh-39510 --- .../springframework/boot/image/paketo/PaketoBuilderTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java index 3aaf09fa7804..478be5eb1bc8 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java @@ -73,6 +73,7 @@ void configureGradleBuild() { this.gradleBuild.scriptPropertyFrom(new File("../../gradle.properties"), "nativeBuildToolsVersion"); this.gradleBuild.expectDeprecationMessages("BPL_SPRING_CLOUD_BINDINGS_ENABLED.*true.*Deprecated"); this.gradleBuild.expectDeprecationMessages("BOM table is deprecated"); + this.gradleBuild.expectDeprecationMessages("Command \"packages\" is deprecated, use `syft scan` instead"); this.gradleBuild.gradleVersion(GradleVersions.maximumCompatible()); } From 7e90b4951b411c92f4731345e4b92c7aec3d7514 Mon Sep 17 00:00:00 2001 From: Jakob Wanger Date: Sat, 10 Feb 2024 15:20:56 -0500 Subject: [PATCH 073/182] Enforce Gradle version to be at least of version 7.5 See gh-39508 Signed-off-by: Jakob Wanger --- .../springframework/boot/gradle/plugin/SpringBootPlugin.java | 4 ++-- .../boot/gradle/plugin/SpringBootPluginIntegrationTests.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java index 3e78fb3cee21..0ff7ca3ac803 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java @@ -117,8 +117,8 @@ public void apply(Project project) { private void verifyGradleVersion() { GradleVersion currentVersion = GradleVersion.current(); - if (currentVersion.compareTo(GradleVersion.version("7.4")) < 0) { - throw new GradleException("Spring Boot plugin requires Gradle 7.x (7.4 or later). " + if (currentVersion.compareTo(GradleVersion.version("7.5")) < 0) { + throw new GradleException("Spring Boot plugin requires Gradle 7.x (7.5 or later). " + "The current version is " + currentVersion); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java index 0776f94cc5d2..59c7cd1b0580 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java @@ -40,9 +40,9 @@ class SpringBootPluginIntegrationTests { @Test @DisabledForJreRange(min = JRE.JAVA_20) void failFastWithVersionOfGradle7LowerThanRequired() { - BuildResult result = this.gradleBuild.gradleVersion("7.3.3").buildAndFail(); + BuildResult result = this.gradleBuild.gradleVersion("7.4.1").buildAndFail(); assertThat(result.getOutput()) - .contains("Spring Boot plugin requires Gradle 7.x (7.4 or later). The current version is Gradle 7.3.3"); + .contains("Spring Boot plugin requires Gradle 7.x (7.5 or later). The current version is Gradle 7.4.1"); } } From 8292104d20025297282562038b5fa4d8b297ed80 Mon Sep 17 00:00:00 2001 From: wanger26 Date: Sat, 10 Feb 2024 14:51:55 -0500 Subject: [PATCH 074/182] Resolve property placeholders when binding properties to a Map Add call to placeholder resolver to ensure property placeholders are resolved for the `MapBinder` See gh-39507 Signed-off-by: wanger26 --- .../boot/context/properties/bind/MapBinder.java | 5 ++++- .../context/properties/bind/MapBinderTests.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java index 1329c7a043ac..c33b2ae92e7c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java @@ -62,7 +62,10 @@ protected Object bindAggregate(ConfigurationPropertyName name, Bindable targe ConfigurationProperty property = source.getConfigurationProperty(name); if (property != null && !hasDescendants) { getContext().setConfigurationProperty(property); - return getContext().getConverter().convert(property.getValue(), target); + Object result = property.getValue(); + result = getContext().getPlaceholdersResolver().resolvePlaceholders(result); + result = getContext().getConverter().convert(result, target); + return result; } source = source.filter(name::isAncestorOf); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java index cb03bcebc451..1bbcebf94e18 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java @@ -610,6 +610,19 @@ void bindToMapWithWildcardShouldConvertToTheRightType() { .containsExactly("127.0.0.1", "127.0.0.2"); } + @Test + void bindToMapWithPlaceholdersShouldResolve() { + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.addConverter(new MapConverter()); + StandardEnvironment environment = new StandardEnvironment(); + Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), conversionService, null, null); + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "bar=bc"); + this.sources.add(new MockConfigurationPropertySource("foo", "a${bar},${bar}d")); + Map map = binder.bind("foo", STRING_STRING_MAP).get(); + assertThat(map).containsKey("abc"); + assertThat(map).containsKey("bcd"); + } + private Bindable> getMapBindable(Class keyGeneric, ResolvableType valueType) { ResolvableType keyType = ResolvableType.forClass(keyGeneric); return Bindable.of(ResolvableType.forClassWithGenerics(Map.class, keyType, valueType)); From f90f29dd12020d9643da87587242e7086902cba4 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Sun, 11 Feb 2024 15:05:48 -0600 Subject: [PATCH 075/182] Polish "Resolve property placeholders when binding properties to a Map" See gh-39507 --- .../boot/context/properties/bind/MapBinder.java | 5 ++--- .../boot/context/properties/bind/MapBinderTests.java | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java index c33b2ae92e7c..57e6234ee757 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -64,8 +64,7 @@ protected Object bindAggregate(ConfigurationPropertyName name, Bindable targe getContext().setConfigurationProperty(property); Object result = property.getValue(); result = getContext().getPlaceholdersResolver().resolvePlaceholders(result); - result = getContext().getConverter().convert(result, target); - return result; + return getContext().getConverter().convert(result, target); } source = source.filter(name::isAncestorOf); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java index 1bbcebf94e18..1a4306298f67 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -615,7 +615,8 @@ void bindToMapWithPlaceholdersShouldResolve() { DefaultConversionService conversionService = new DefaultConversionService(); conversionService.addConverter(new MapConverter()); StandardEnvironment environment = new StandardEnvironment(); - Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), conversionService, null, null); + Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), + conversionService, null, null); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "bar=bc"); this.sources.add(new MockConfigurationPropertySource("foo", "a${bar},${bar}d")); Map map = binder.bind("foo", STRING_STRING_MAP).get(); From 02765bc9f0b21b963a3f29e774a45c9558148a32 Mon Sep 17 00:00:00 2001 From: Jakob Wanger Date: Sat, 10 Feb 2024 15:35:59 -0500 Subject: [PATCH 076/182] Clarify that auto-configured OpenTelemetry Resource behaviour The documentation does not describe that exposing a Resource bean, will prevent the property from being able to provide attributes (unless the newly exposed Resource bean, implements it). Signed-off-by: Jakob Wanger See gh-39509 --- .../src/docs/asciidoc/actuator/observability.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc index e0b02262c7b6..efff390d2067 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc @@ -80,7 +80,7 @@ Spring Boot's actuator module includes basic support for https://opentelemetry.i It provides a bean of type `OpenTelemetry`, and if there are beans of type `SdkTracerProvider`, `ContextPropagators`, `SdkLoggerProvider` or `SdkMeterProvider` in the application context, they automatically get registered. Additionally, it provides a `Resource` bean. -The attributes of the `Resource` can be configured via the configprop:management.opentelemetry.resource-attributes[] configuration property. +The attributes of the `Resource` can be configured via the configprop:management.opentelemetry.resource-attributes[] configuration property if you have not defined and exposed your own Resource bean. NOTE: Spring Boot does not provide auto-configuration for OpenTelemetry metrics or logging. OpenTelemetry tracing is only auto-configured when used together with <>. From 6163308fbc24f3f6cbc8f73ca65be5b9d9f85dab Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 12 Feb 2024 08:20:24 +0100 Subject: [PATCH 077/182] Polish "Clarify that auto-configured OpenTelemetry Resource behaviour" See gh-39509 --- .../src/docs/asciidoc/actuator/observability.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc index efff390d2067..54d2e5ba4c96 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc @@ -80,7 +80,8 @@ Spring Boot's actuator module includes basic support for https://opentelemetry.i It provides a bean of type `OpenTelemetry`, and if there are beans of type `SdkTracerProvider`, `ContextPropagators`, `SdkLoggerProvider` or `SdkMeterProvider` in the application context, they automatically get registered. Additionally, it provides a `Resource` bean. -The attributes of the `Resource` can be configured via the configprop:management.opentelemetry.resource-attributes[] configuration property if you have not defined and exposed your own Resource bean. +The attributes of the auto-configured `Resource` can be configured via the configprop:management.opentelemetry.resource-attributes[] configuration property. +If you have defined your own `Resource` bean, this will no longer be the case. NOTE: Spring Boot does not provide auto-configuration for OpenTelemetry metrics or logging. OpenTelemetry tracing is only auto-configured when used together with <>. From c1df48f9691fa1e306af9e26c6a4b03bb2f1e7fc Mon Sep 17 00:00:00 2001 From: dev-chpark Date: Mon, 12 Feb 2024 16:25:16 +0900 Subject: [PATCH 078/182] Rename exception variable name See gh-39518 --- .../java/org/springframework/boot/ansi/AnsiPropertySource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java index 1553ead56d57..cef283361653 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java @@ -150,7 +150,7 @@ AnsiElement getElement(String postfix) { try { return this.factory.apply(Integer.parseInt(postfix)); } - catch (IllegalArgumentException ex) { + catch (IllegalArgumentException ignored) { } } return null; From 8ffcfc9b77ca99016fb486e9de340217b5a57e05 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 12 Feb 2024 10:09:29 +0100 Subject: [PATCH 079/182] Harmonize style of igored exceptions across the codebase --- .../server/ManagementWebServerFactoryCustomizer.java | 3 ++- .../invoker/cache/CachingOperationInvoker.java | 3 ++- .../boot/actuate/health/HealthEndpointTests.java | 3 ++- ...SharedMetadataReaderFactoryContextInitializer.java | 3 ++- .../boot/autoconfigure/cache/CacheCondition.java | 3 ++- .../boot/autoconfigure/condition/OnBeanCondition.java | 3 ++- .../embedded/UndertowWebServerFactoryCustomizer.java | 3 ++- .../web/servlet/WebMvcAutoConfiguration.java | 3 ++- .../web/servlet/error/DefaultErrorViewResolver.java | 3 ++- .../batch/BatchAutoConfigurationTests.java | 3 ++- .../session/SessionAutoConfigurationTests.java | 3 ++- .../lifecycle/TcpConnectServiceReadinessCheck.java | 3 ++- .../autoconfigure/json/JsonTypeExcludeFilter.java | 3 ++- .../boot/test/context/ImportsContextCustomizer.java | 3 ++- .../boot/test/context/SpringBootContextLoader.java | 2 ++ .../context/assertj/ApplicationContextAssert.java | 3 ++- .../boot/test/json/AbstractJsonMarshalTester.java | 3 ++- .../boot/test/json/JsonContentAssert.java | 3 ++- ...stcontainersLifecycleBeanFactoryPostProcessor.java | 3 ++- .../connection/ContainerConnectionDetailsFactory.java | 3 ++- .../platform/docker/ssl/PrivateKeyParser.java | 3 ++- .../platform/docker/TotalProgressListenerTests.java | 3 ++- .../boot/configurationprocessor/json/JSON.java | 11 +++++++---- .../boot/configurationprocessor/json/JSONObject.java | 5 +++-- .../boot/configurationprocessor/json/JSONTokener.java | 5 +++-- .../boot/gradle/tasks/bundling/BootZipCopyAction.java | 3 ++- .../boot/loader/LaunchedURLClassLoader.java | 3 ++- .../boot/loader/archive/JarFileArchive.java | 3 ++- .../org/springframework/boot/loader/jar/Handler.java | 6 +++++- .../org/springframework/boot/loader/jar/JarFile.java | 3 ++- .../boot/maven/JarIntegrationTests.java | 3 ++- .../boot/maven/WarIntegrationTests.java | 3 ++- .../classpath/ModifiedClassPathClassLoader.java | 4 +++- .../springframework/boot/ansi/AnsiPropertySource.java | 5 +++-- .../properties/ConfigurationPropertiesBean.java | 3 ++- .../bind/handler/NoUnboundElementsBindHandler.java | 3 ++- .../bind/validation/ValidationBindHandler.java | 3 ++- .../ConfigurationPropertySourcesPropertyResolver.java | 4 +++- .../properties/source/DefaultPropertyMapper.java | 3 ++- .../source/SpringConfigurationPropertySource.java | 3 ++- .../boot/origin/TextResourceOrigin.java | 3 ++- .../boot/ssl/pem/PemPrivateKeyParser.java | 1 + .../springframework/boot/system/ApplicationHome.java | 5 ++++- .../boot/web/embedded/netty/NettyWebServer.java | 3 ++- .../boot/web/embedded/undertow/UndertowWebServer.java | 3 ++- .../boot/web/servlet/support/ErrorPageFilter.java | 3 ++- .../buffering/BufferingApplicationStartupTests.java | 3 ++- .../context/properties/bind/BindConverterTests.java | 3 ++- .../ApplicationContextRequestMatcherTests.java | 2 ++ .../server/AbstractServletWebServerFactoryTests.java | 4 ++-- .../context/embedded/AbstractApplicationLauncher.java | 3 ++- 51 files changed, 116 insertions(+), 55 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java index 0e1746e3e607..aa13066f1419 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -81,6 +81,7 @@ private void customizeSameAsParentContext(T factory) { customizers.add(BeanFactoryUtils.beanOfTypeIncludingAncestors(this.beanFactory, customizerClass)); } catch (NoSuchBeanDefinitionException ex) { + // Ignore } } invokeCustomizers(factory, customizers); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvoker.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvoker.java index 6e24168e6258..8cd51645de92 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvoker.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -110,6 +110,7 @@ private void cleanExpiredCachedResponses(long accessTime) { this.cachedResponses.entrySet().removeIf((entry) -> entry.getValue().isStale(accessTime, this.timeToLive)); } catch (Exception ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java index 167ad6a0bc5e..347b8b881e9a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/HealthEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -79,6 +79,7 @@ void healthWhenIndicatorIsSlow(CapturedOutput output) { Thread.sleep(100); } catch (InterruptedException ex) { + // Ignore } return this.up; }; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java index d26f3d0d6b91..8ffcaa58e77b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -124,6 +124,7 @@ private void configureConfigurationClassPostProcessor(BeanDefinitionRegistry reg registry.getBeanDefinition(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } catch (NoSuchBeanDefinitionException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java index 884bf693d651..34159a584b5b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -56,6 +56,7 @@ public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeM } } catch (BindException ex) { + // Ignore } return ConditionOutcome.noMatch(message.because("unknown cache type")); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java index 60f0f90cdd54..b90ac437e933 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -500,6 +500,7 @@ private Set> resolveWhenPossible(Set classNames) { resolved.add(resolve(className, this.classLoader)); } catch (ClassNotFoundException | NoClassDefFoundError ex) { + // Ignore } } return resolved; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java index d5d861aad7c6..fc9640ba10b4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/UndertowWebServerFactoryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -164,6 +164,7 @@ private abstract static class AbstractOptions { lookup.put(getCanonicalName(field.getName()), option); } catch (IllegalAccessException ex) { + // Ignore } } }); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index e92256d6004a..ada52f53cd8c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -514,6 +514,7 @@ private Resource getIndexHtmlResource(Resource location) { } } catch (Exception ex) { + // Ignore } return null; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewResolver.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewResolver.java index e10df19a51b2..23474a1dc5b7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewResolver.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -126,6 +126,7 @@ private ModelAndView resolveResource(String viewName, Map model) } } catch (Exception ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index 36a74d8649dc..192dd2f53f56 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -584,6 +584,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw jobRegistry.register(getJobFactory()); } catch (DuplicateJobException ex) { + // Ignore } } return bean; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java index b3f557101d68..eabb3a4655c6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -106,6 +106,7 @@ void filterIsRegisteredWithAsyncErrorAndRequestDispatcherTypes() { delegatingFilterProxy.doFilter(null, null, null); } catch (Exception ex) { + // Ignore } assertThat(delegatingFilterProxy).extracting("delegate") .isSameAs(context.getBean(SessionRepositoryFilter.class)); diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/TcpConnectServiceReadinessCheck.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/TcpConnectServiceReadinessCheck.java index ee00bd9d1b03..1cfd2b60acc4 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/TcpConnectServiceReadinessCheck.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/lifecycle/TcpConnectServiceReadinessCheck.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -72,6 +72,7 @@ private void check(RunningService service, int port, Socket socket) throws IOExc } } catch (SocketTimeoutException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/JsonTypeExcludeFilter.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/JsonTypeExcludeFilter.java index 2f6479aafe5b..160aad341212 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/JsonTypeExcludeFilter.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/JsonTypeExcludeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2024 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. @@ -43,6 +43,7 @@ public final class JsonTypeExcludeFilter extends StandardAnnotationCustomizableT includes.add(ClassUtils.forName(JACKSON_MODULE, null)); } catch (Exception ex) { + // Ignore } includes.add(JsonComponent.class); DEFAULT_INCLUDES = Collections.unmodifiableSet(includes); diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java index cea86533e636..4ec97096d575 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -205,6 +205,7 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t registry.removeBeanDefinition(ImportsConfiguration.BEAN_NAME); } catch (NoSuchBeanDefinitionException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java index cb646facf696..663f56fa818e 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java @@ -167,6 +167,7 @@ private Method getMainMethod(MergedContextConfiguration mergedConfig, UseMainMet mainMethod = ReflectionUtils.findMethod(kotlinClass, "main", String[].class); } catch (ClassNotFoundException ex) { + // Ignore } } Assert.state(mainMethod != null || useMainMethod == UseMainMethod.WHEN_AVAILABLE, @@ -548,6 +549,7 @@ private ApplicationContext run(ThrowingSupplier } } catch (AbandonedRunException ex) { + // Ignore } catch (Exception ex) { if (this.failedContexts.size() == 1) { diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/assertj/ApplicationContextAssert.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/assertj/ApplicationContextAssert.java index 317593cb682b..02fa5109d8bf 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/assertj/ApplicationContextAssert.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/assertj/ApplicationContextAssert.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -203,6 +203,7 @@ public ApplicationContextAssert doesNotHaveBean(String name) { getApplicationContext(), name, bean)); } catch (NoSuchBeanDefinitionException ex) { + // Ignore } return this; } diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java index 449ba819ad30..ae9066273f0e 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/AbstractJsonMarshalTester.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2024 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. @@ -316,6 +316,7 @@ private void closeQuietly(Closeable closeable) { closeable.close(); } catch (IOException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java index bd00e51232ee..797abc24de5f 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/json/JsonContentAssert.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -1095,6 +1095,7 @@ void assertDoesNotHavePath() { failWithMessage("Expecting no JSON path \"%s\"", this.expression); } catch (PathNotFoundException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanFactoryPostProcessor.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanFactoryPostProcessor.java index 516eb45026fd..cb193482b588 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanFactoryPostProcessor.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/lifecycle/TestcontainersLifecycleBeanFactoryPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -50,6 +50,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) } } catch (NoSuchBeanDefinitionException ex) { + // Ignore } } } diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java index 2a41db031fdc..d2edbd9db575 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -93,6 +93,7 @@ public final D getConnectionDetails(ContainerConnectionSource source) { } } catch (NoClassDefFoundError ex) { + // Ignore } return null; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PrivateKeyParser.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PrivateKeyParser.java index e2b5259a11e7..480392a032a5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PrivateKeyParser.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ssl/PrivateKeyParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -203,6 +203,7 @@ private PrivateKey parse(byte[] bytes) { return keyFactory.generatePrivate(keySpec); } catch (InvalidKeySpecException | NoSuchAlgorithmException ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListenerTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListenerTests.java index 1dd2db0e3dcf..b61faba2673a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListenerTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/TotalProgressListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2024 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. @@ -78,6 +78,7 @@ public void onUpdate(TestImageUpdateEvent event) { Thread.sleep(10); } catch (InterruptedException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSON.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSON.java index 058f5674e4db..242705b599ac 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSON.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSON.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright 2012-2024 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. @@ -51,7 +51,8 @@ static Double toDouble(Object value) { try { return Double.valueOf((String) value); } - catch (NumberFormatException ignored) { + catch (NumberFormatException ex) { + // Ignore } } return null; @@ -68,7 +69,8 @@ static Integer toInteger(Object value) { try { return (int) Double.parseDouble((String) value); } - catch (NumberFormatException ignored) { + catch (NumberFormatException ex) { + // Ignore } } return null; @@ -85,7 +87,8 @@ static Long toLong(Object value) { try { return (long) Double.parseDouble((String) value); } - catch (NumberFormatException ignored) { + catch (NumberFormatException ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONObject.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONObject.java index a4cdb2025748..66e4e36e6846 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONObject.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONObject.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright 2012-2024 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. @@ -827,7 +827,8 @@ else if (o.getClass().isArray()) { return o.toString(); } } - catch (Exception ignored) { + catch (Exception ex) { + // Ignore } return null; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONTokener.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONTokener.java index 3e390ec97fd6..be1672533f1f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONTokener.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/json-shade/java/org/springframework/boot/configurationprocessor/json/JSONTokener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright 2012-2024 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. @@ -320,7 +320,8 @@ else if (number.startsWith("0") && number.length() > 1) { try { return Double.valueOf(literal); } - catch (NumberFormatException ignored) { + catch (NumberFormatException ex) { + // Ignore } /* ... finally give up. We have an unquoted string */ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java index 6e9606f4dab0..53ccdcece2cb 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -196,6 +196,7 @@ private void closeQuietly(OutputStream outputStream) { outputStream.close(); } catch (IOException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java index 8c7cf98ae130..1c88bba02d78 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -127,6 +127,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE return result; } catch (ClassNotFoundException ex) { + // Ignore } } if (this.exploded) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java index b30c8bb37a52..2220205bdeff 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -151,6 +151,7 @@ private Path createUnpackDirectory(Path parent) { return unpackDirectory; } catch (IOException ex) { + // Ignore } } throw new IllegalStateException("Failed to create unpack directory in directory '" + parent + "'"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java index 67bf8048f046..4fe58b7f4472 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -140,6 +140,7 @@ private URLConnection openFallbackTomcatConnection(URL url) { return connection; } catch (IOException ex) { + // Ignore } } return null; @@ -154,6 +155,7 @@ private boolean isTomcatWarUrl(String file) { } } catch (Exception ex) { + // Ignore } } return false; @@ -174,6 +176,7 @@ private URLConnection openFallbackContextConnection(URL url) { } } catch (Exception ex) { + // Ignore } return null; } @@ -425,6 +428,7 @@ static void captureJarContextUrl() { } } catch (Exception ex) { + // Ignore } } finally { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java index 502c450fa738..ba221b7f0c53 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -144,6 +144,7 @@ private JarFile(RandomAccessDataFile rootFile, String pathFromRoot, RandomAccess super.close(); } catch (IOException ioex) { + // Ignore } throw ex; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java index 46ad4f7f3a83..e964c2ecee78 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/JarIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -329,6 +329,7 @@ void repackagedJarContainsTheLayersIndexByDefault(MavenBuild mavenBuild) { .anyMatch((dependency) -> dependency.startsWith("BOOT-INF/lib/log4j-api-2")); } catch (IOException ex) { + // Ignore } }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java index 77fd8842ec71..01a4d8cb54df 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/WarIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -166,6 +166,7 @@ void repackagedWarContainsTheLayersIndexByDefault(MavenBuild mavenBuild) { .anyMatch((dependency) -> dependency.startsWith("WEB-INF/lib-provided/")); } catch (IOException ex) { + // Ignore } }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/classpath/ModifiedClassPathClassLoader.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/classpath/ModifiedClassPathClassLoader.java index 53dd3b99dfca..a5db6b97e9c4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/classpath/ModifiedClassPathClassLoader.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/classpath/ModifiedClassPathClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -176,6 +176,7 @@ private static boolean isShortenedIntelliJJar(URL url) { return createdBy != null && createdBy.contains("IntelliJ"); } catch (Exception ex) { + // Ignore } } return false; @@ -309,6 +310,7 @@ private boolean isExcluded(URL url) { } } catch (URISyntaxException ex) { + // Ignore } } return false; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java index cef283361653..50b61eb1eb92 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiPropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2024 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. @@ -150,7 +150,8 @@ AnsiElement getElement(String postfix) { try { return this.factory.apply(Integer.parseInt(postfix)); } - catch (IllegalArgumentException ignored) { + catch (IllegalArgumentException ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java index 186184b7c8b1..f63065527122 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -171,6 +171,7 @@ private static Map getAll(ConfigurableAppli } } catch (Exception ex) { + // Ignore } } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/handler/NoUnboundElementsBindHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/handler/NoUnboundElementsBindHandler.java index f5c6a488c692..14c8ef67277d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/handler/NoUnboundElementsBindHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/handler/NoUnboundElementsBindHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2024 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. @@ -110,6 +110,7 @@ private void collectUnbound(ConfigurationPropertyName name, Set isUnbound(name, candidate)).getConfigurationProperty(unboundName)); } catch (Exception ex) { + // Ignore } } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/validation/ValidationBindHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/validation/ValidationBindHandler.java index 26224addd924..b92e2b8c7509 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/validation/ValidationBindHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/validation/ValidationBindHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -212,6 +212,7 @@ private T getBoundField(Map boundFields, Strin } } catch (Exception ex) { + // Ignore } return null; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertySourcesPropertyResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertySourcesPropertyResolver.java index f11fc89dc7d8..9cb2d77b7364 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertySourcesPropertyResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertySourcesPropertyResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -49,6 +49,7 @@ public boolean containsProperty(String key) { return attached.findConfigurationProperty(name) != null; } catch (Exception ex) { + // Ignore } } } @@ -91,6 +92,7 @@ private Object findPropertyValue(String key) { return (configurationProperty != null) ? configurationProperty.getValue() : null; } catch (Exception ex) { + // Ignore } } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/DefaultPropertyMapper.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/DefaultPropertyMapper.java index 05ead2bddaee..e679b541d1a8 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/DefaultPropertyMapper.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/DefaultPropertyMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2024 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. @@ -75,6 +75,7 @@ private ConfigurationPropertyName tryMap(String propertySourceName) { } } catch (Exception ex) { + // Ignore } return ConfigurationPropertyName.EMPTY; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java index 8c683db01d3d..df9f76994fc2 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -89,6 +89,7 @@ public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName } } catch (Exception ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/origin/TextResourceOrigin.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/origin/TextResourceOrigin.java index 1283dbbf0df2..6e69343c7d81 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/origin/TextResourceOrigin.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/origin/TextResourceOrigin.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -121,6 +121,7 @@ private String getResourceDescription(ClassPathResource resource) { } } catch (IOException ex) { + // Ignore } return resource.getDescription(); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java index 087e517292ec..0f67ff854c42 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java @@ -261,6 +261,7 @@ private PrivateKey parse(byte[] bytes, String password) { return keyFactory.generatePrivate(keySpec); } catch (InvalidKeySpecException | NoSuchAlgorithmException ex) { + // Ignore } } return null; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/system/ApplicationHome.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/system/ApplicationHome.java index cd05e9c023db..5d0b3b6f26c2 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/system/ApplicationHome.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/system/ApplicationHome.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -82,6 +82,7 @@ private Class getStartClass(Enumeration manifestResources) { } } catch (Exception ex) { + // Ignore } } return null; @@ -98,6 +99,7 @@ private File findSource(Class sourceClass) { } } catch (Exception ex) { + // Ignore } return null; } @@ -112,6 +114,7 @@ private boolean isUnitTest() { } } catch (Exception ex) { + // Ignore } return false; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java index 8b555f350f75..c441b8837d0d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/NettyWebServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -128,6 +128,7 @@ private void tryAppend(StringBuilder message, String format, Supplier su message.append(String.format(format, value)); } catch (UnsupportedOperationException ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java index dd7f887bfb69..c4045af0cad3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowWebServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -155,6 +155,7 @@ private void closeSilently(Closeable closeable) { closeable.close(); } catch (Exception ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilter.java index a4a4d813c462..d1a615718cc4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/support/ErrorPageFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -304,6 +304,7 @@ private static void addClassIfPresent(Collection> collection, String cl collection.add(ClassUtils.forName(className, null)); } catch (Throwable ex) { + // Ignore } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartupTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartupTests.java index efc50373185c..d146f4750714 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartupTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/metrics/buffering/BufferingApplicationStartupTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -139,6 +139,7 @@ void multiThreadedAccessShouldWork() throws InterruptedException { Thread.sleep(1); } catch (InterruptedException ex) { + // Ignore } step.end(); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java index 6768f00cff1b..827839d543a4 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -208,6 +208,7 @@ void convertWhenUsingTypeConverterConversionServiceFromMultipleThreads() { thread.join(); } catch (InterruptedException ex) { + // Ignore } } assertThat(results).isNotEmpty().doesNotContainNull(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcherTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcherTests.java index cb028295eed0..e8aae88112c2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcherTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/security/servlet/ApplicationContextRequestMatcherTests.java @@ -133,6 +133,7 @@ private void join(Thread thread) { thread.join(1000); } catch (InterruptedException ex) { + // Ignore } } @@ -205,6 +206,7 @@ protected void initialized(Supplier context) { Thread.sleep(200); } catch (InterruptedException ex) { + // Ignore } this.initialized.set(true); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index 0cb29be33cf5..0e96fed0206b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -1262,7 +1262,7 @@ void whenARequestIsActiveThenStopWillComplete() throws InterruptedException { blockingServlet.admitOne(); } catch (RuntimeException ex) { - + // Ignore } } @@ -1318,7 +1318,7 @@ void whenARequestIsActiveAfterGracefulShutdownEndsThenStopWillComplete() throws blockingServlet.admitOne(); } catch (RuntimeException ex) { - + // Ignore } } diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/intTest/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java b/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/intTest/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java index b60b41e220e7..fabd0e4a56b8 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/intTest/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/intTest/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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. @@ -132,6 +132,7 @@ public void run() { StreamUtils.copy(this.input, this.output); } catch (IOException ex) { + // Ignore } } From 4319554f8a721442993b4538f1828dbc5949a5dd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 12 Feb 2024 10:13:04 +0000 Subject: [PATCH 080/182] Fix mapping of boolean properties to Gson's builder Fixes gh-39504 --- .../gson/GsonAutoConfiguration.java | 19 +++-- .../gson/GsonAutoConfigurationTests.java | 80 ++++++++++++++++--- 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java index 4fd3f99778cc..f81ecacf007f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -78,17 +78,22 @@ public int getOrder() { public void customize(GsonBuilder builder) { GsonProperties properties = this.properties; PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(properties::getGenerateNonExecutableJson).toCall(builder::generateNonExecutableJson); + map.from(properties::getGenerateNonExecutableJson).whenTrue().toCall(builder::generateNonExecutableJson); map.from(properties::getExcludeFieldsWithoutExposeAnnotation) + .whenTrue() .toCall(builder::excludeFieldsWithoutExposeAnnotation); map.from(properties::getSerializeNulls).whenTrue().toCall(builder::serializeNulls); - map.from(properties::getEnableComplexMapKeySerialization).toCall(builder::enableComplexMapKeySerialization); - map.from(properties::getDisableInnerClassSerialization).toCall(builder::disableInnerClassSerialization); + map.from(properties::getEnableComplexMapKeySerialization) + .whenTrue() + .toCall(builder::enableComplexMapKeySerialization); + map.from(properties::getDisableInnerClassSerialization) + .whenTrue() + .toCall(builder::disableInnerClassSerialization); map.from(properties::getLongSerializationPolicy).to(builder::setLongSerializationPolicy); map.from(properties::getFieldNamingPolicy).to(builder::setFieldNamingPolicy); - map.from(properties::getPrettyPrinting).toCall(builder::setPrettyPrinting); - map.from(properties::getLenient).toCall(builder::setLenient); - map.from(properties::getDisableHtmlEscaping).toCall(builder::disableHtmlEscaping); + map.from(properties::getPrettyPrinting).whenTrue().toCall(builder::setPrettyPrinting); + map.from(properties::getLenient).whenTrue().toCall(builder::setLenient); + map.from(properties::getDisableHtmlEscaping).whenFalse().toCall(builder::disableHtmlEscaping); map.from(properties::getDateFormat).to(builder::setDateFormat); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java index 9084e4a4940d..e53b013aefaf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -59,7 +59,7 @@ void gsonRegistration() { } @Test - void generateNonExecutableJson() { + void generateNonExecutableJsonTrue() { this.contextRunner.withPropertyValues("spring.gson.generate-non-executable-json:true").run((context) -> { Gson gson = context.getBean(Gson.class); assertThat(gson.toJson(new DataObject())).isNotEqualTo("{\"data\":1}"); @@ -68,7 +68,15 @@ void generateNonExecutableJson() { } @Test - void excludeFieldsWithoutExposeAnnotation() { + void generateNonExecutableJsonFalse() { + this.contextRunner.withPropertyValues("spring.gson.generate-non-executable-json:false").run((context) -> { + Gson gson = context.getBean(Gson.class); + assertThat(gson.toJson(new DataObject())).isEqualTo("{\"data\":1}"); + }); + } + + @Test + void excludeFieldsWithoutExposeAnnotationTrue() { this.contextRunner.withPropertyValues("spring.gson.exclude-fields-without-expose-annotation:true") .run((context) -> { Gson gson = context.getBean(Gson.class); @@ -76,6 +84,15 @@ void excludeFieldsWithoutExposeAnnotation() { }); } + @Test + void excludeFieldsWithoutExposeAnnotationFalse() { + this.contextRunner.withPropertyValues("spring.gson.exclude-fields-without-expose-annotation:false") + .run((context) -> { + Gson gson = context.getBean(Gson.class); + assertThat(gson.toJson(new DataObject())).isEqualTo("{\"data\":1}"); + }); + } + @Test void serializeNullsTrue() { this.contextRunner.withPropertyValues("spring.gson.serialize-nulls:true").run((context) -> { @@ -93,7 +110,7 @@ void serializeNullsFalse() { } @Test - void enableComplexMapKeySerialization() { + void enableComplexMapKeySerializationTrue() { this.contextRunner.withPropertyValues("spring.gson.enable-complex-map-key-serialization:true") .run((context) -> { Gson gson = context.getBean(Gson.class); @@ -103,6 +120,17 @@ void enableComplexMapKeySerialization() { }); } + @Test + void enableComplexMapKeySerializationFalse() { + this.contextRunner.withPropertyValues("spring.gson.enable-complex-map-key-serialization:false") + .run((context) -> { + Gson gson = context.getBean(Gson.class); + Map original = new LinkedHashMap<>(); + original.put(new DataObject(), "a"); + assertThat(gson.toJson(original)).contains(DataObject.class.getName()).doesNotContain("\"data\":"); + }); + } + @Test void notDisableInnerClassSerialization() { this.contextRunner.run((context) -> { @@ -113,7 +141,7 @@ void notDisableInnerClassSerialization() { } @Test - void disableInnerClassSerialization() { + void disableInnerClassSerializationTrue() { this.contextRunner.withPropertyValues("spring.gson.disable-inner-class-serialization:true").run((context) -> { Gson gson = context.getBean(Gson.class); WrapperObject wrapperObject = new WrapperObject(); @@ -121,6 +149,15 @@ void disableInnerClassSerialization() { }); } + @Test + void disableInnerClassSerializationFalse() { + this.contextRunner.withPropertyValues("spring.gson.disable-inner-class-serialization:false").run((context) -> { + Gson gson = context.getBean(Gson.class); + WrapperObject wrapperObject = new WrapperObject(); + assertThat(gson.toJson(wrapperObject.new NestedObject())).isEqualTo("{\"data\":\"nested\"}"); + }); + } + @Test void withLongSerializationPolicy() { this.contextRunner.withPropertyValues("spring.gson.long-serialization-policy:" + LongSerializationPolicy.STRING) @@ -156,13 +193,21 @@ void customGsonBuilder() { } @Test - void withPrettyPrinting() { + void withPrettyPrintingTrue() { this.contextRunner.withPropertyValues("spring.gson.pretty-printing:true").run((context) -> { Gson gson = context.getBean(Gson.class); assertThat(gson.toJson(new DataObject())).isEqualTo("{\n \"data\": 1\n}"); }); } + @Test + void withPrettyPrintingFalse() { + this.contextRunner.withPropertyValues("spring.gson.pretty-printing:false").run((context) -> { + Gson gson = context.getBean(Gson.class); + assertThat(gson.toJson(new DataObject())).isEqualTo("{\"data\":1}"); + }); + } + @Test void withoutLenient() { this.contextRunner.run((context) -> { @@ -172,7 +217,7 @@ void withoutLenient() { } @Test - void withLenient() { + void withLenientTrue() { this.contextRunner.withPropertyValues("spring.gson.lenient:true").run((context) -> { Gson gson = context.getBean(Gson.class); assertThat(gson).hasFieldOrPropertyWithValue("lenient", true); @@ -180,7 +225,15 @@ void withLenient() { } @Test - void withHtmlEscaping() { + void withLenientFalse() { + this.contextRunner.withPropertyValues("spring.gson.lenient:false").run((context) -> { + Gson gson = context.getBean(Gson.class); + assertThat(gson).hasFieldOrPropertyWithValue("lenient", false); + }); + } + + @Test + void withoutDisableHtmlEscaping() { this.contextRunner.run((context) -> { Gson gson = context.getBean(Gson.class); assertThat(gson.htmlSafe()).isTrue(); @@ -188,12 +241,19 @@ void withHtmlEscaping() { } @Test - void withoutHtmlEscaping() { + void withDisableHtmlEscapingTrue() { this.contextRunner.withPropertyValues("spring.gson.disable-html-escaping:true").run((context) -> { Gson gson = context.getBean(Gson.class); - assertThat(gson.htmlSafe()).isFalse(); + assertThat(gson.htmlSafe()).isTrue(); }); + } + @Test + void withDisableHtmlEscapingFalse() { + this.contextRunner.withPropertyValues("spring.gson.disable-html-escaping:false").run((context) -> { + Gson gson = context.getBean(Gson.class); + assertThat(gson.htmlSafe()).isFalse(); + }); } @Test From d597a4d56b8e87c6cd72a9dd02213e563b54a416 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 12 Feb 2024 12:35:47 +0000 Subject: [PATCH 081/182] Correct handling of disable-html-escaping See gh-39504 --- .../boot/autoconfigure/gson/GsonAutoConfiguration.java | 2 +- .../boot/autoconfigure/gson/GsonAutoConfigurationTests.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java index f81ecacf007f..94ed69c74517 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.java @@ -93,7 +93,7 @@ public void customize(GsonBuilder builder) { map.from(properties::getFieldNamingPolicy).to(builder::setFieldNamingPolicy); map.from(properties::getPrettyPrinting).whenTrue().toCall(builder::setPrettyPrinting); map.from(properties::getLenient).whenTrue().toCall(builder::setLenient); - map.from(properties::getDisableHtmlEscaping).whenFalse().toCall(builder::disableHtmlEscaping); + map.from(properties::getDisableHtmlEscaping).whenTrue().toCall(builder::disableHtmlEscaping); map.from(properties::getDateFormat).to(builder::setDateFormat); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java index e53b013aefaf..179280d8d180 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/gson/GsonAutoConfigurationTests.java @@ -244,7 +244,7 @@ void withoutDisableHtmlEscaping() { void withDisableHtmlEscapingTrue() { this.contextRunner.withPropertyValues("spring.gson.disable-html-escaping:true").run((context) -> { Gson gson = context.getBean(Gson.class); - assertThat(gson.htmlSafe()).isTrue(); + assertThat(gson.htmlSafe()).isFalse(); }); } @@ -252,7 +252,7 @@ void withDisableHtmlEscapingTrue() { void withDisableHtmlEscapingFalse() { this.contextRunner.withPropertyValues("spring.gson.disable-html-escaping:false").run((context) -> { Gson gson = context.getBean(Gson.class); - assertThat(gson.htmlSafe()).isFalse(); + assertThat(gson.htmlSafe()).isTrue(); }); } From b6467ed826818db5d18061496768db3f6758c916 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 12 Feb 2024 14:10:03 +0000 Subject: [PATCH 082/182] Adapt to Spring Data Neo4j now requiring a transaction manager See gh-39493 --- .../neo4j/Neo4jDataAutoConfiguration.java | 30 +---------- .../Neo4jReactiveDataAutoConfiguration.java | 10 +++- .../Neo4jRepositoriesAutoConfiguration.java | 3 ++ .../Neo4jTransactionManagerConfiguration.java | 48 +++++++++++++++++ ...jTransactionalComponentsConfiguration.java | 54 +++++++++++++++++++ 5 files changed, 116 insertions(+), 29 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionManagerConfiguration.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionalComponentsConfiguration.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java index 38cad56487c8..1970e5449725 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java @@ -20,7 +20,6 @@ import org.neo4j.driver.Driver; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -30,23 +29,18 @@ import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.neo4j.aot.Neo4jManagedTypes; import org.springframework.data.neo4j.core.DatabaseSelectionProvider; -import org.springframework.data.neo4j.core.Neo4jClient; -import org.springframework.data.neo4j.core.Neo4jOperations; -import org.springframework.data.neo4j.core.Neo4jTemplate; import org.springframework.data.neo4j.core.convert.Neo4jConversions; import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext; import org.springframework.data.neo4j.core.schema.Node; import org.springframework.data.neo4j.core.schema.RelationshipProperties; import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager; -import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension; import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionManager; /** * {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j. @@ -64,6 +58,7 @@ @ConditionalOnClass({ Driver.class, Neo4jTransactionManager.class, PlatformTransactionManager.class }) @EnableConfigurationProperties(Neo4jDataProperties.class) @ConditionalOnBean(Driver.class) +@Import({ Neo4jTransactionManagerConfiguration.class, Neo4jTransactionalComponentsConfiguration.class }) public class Neo4jDataAutoConfiguration { @Bean @@ -96,25 +91,4 @@ public DatabaseSelectionProvider databaseSelectionProvider(Neo4jDataProperties p : DatabaseSelectionProvider.getDefaultSelectionProvider(); } - @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME) - @ConditionalOnMissingBean - public Neo4jClient neo4jClient(Driver driver, DatabaseSelectionProvider databaseNameProvider) { - return Neo4jClient.create(driver, databaseNameProvider); - } - - @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME) - @ConditionalOnMissingBean(Neo4jOperations.class) - public Neo4jTemplate neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext) { - return new Neo4jTemplate(neo4jClient, neo4jMappingContext); - } - - @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) - @ConditionalOnMissingBean(TransactionManager.class) - public Neo4jTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider, - ObjectProvider optionalCustomizers) { - Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider); - optionalCustomizers.ifAvailable((customizer) -> customizer.customize((TransactionManager) transactionManager)); - return transactionManager; - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java index 94fa7836d314..b3c4752c0faf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jReactiveDataAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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,6 +30,7 @@ import org.springframework.data.neo4j.core.ReactiveNeo4jOperations; import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate; import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext; +import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager; import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension; import org.springframework.transaction.ReactiveTransactionManager; @@ -68,4 +69,11 @@ public ReactiveNeo4jTemplate reactiveNeo4jTemplate(ReactiveNeo4jClient neo4jClie return new ReactiveNeo4jTemplate(neo4jClient, neo4jMappingContext); } + @Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) + @ConditionalOnMissingBean(ReactiveTransactionManager.class) + ReactiveNeo4jTransactionManager rectiveNeo4jTransactionManager(Driver driver, + ReactiveDatabaseSelectionProvider databaseNameProvider) { + return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider); + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jRepositoriesAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jRepositoriesAutoConfiguration.java index 05f2c7729e14..321407c2c6ff 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jRepositoriesAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jRepositoriesAutoConfiguration.java @@ -20,11 +20,13 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType; import org.springframework.boot.autoconfigure.data.RepositoryType; import org.springframework.context.annotation.Import; +import org.springframework.data.neo4j.core.Neo4jTemplate; import org.springframework.data.neo4j.repository.Neo4jRepository; import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension; @@ -52,6 +54,7 @@ @AutoConfiguration(after = Neo4jDataAutoConfiguration.class) @ConditionalOnClass({ Driver.class, Neo4jRepository.class }) @ConditionalOnMissingBean({ Neo4jRepositoryFactoryBean.class, Neo4jRepositoryConfigurationExtension.class }) +@ConditionalOnBean(Neo4jTemplate.class) @ConditionalOnRepositoryType(store = "neo4j", type = RepositoryType.IMPERATIVE) @Import(Neo4jRepositoriesRegistrar.class) public class Neo4jRepositoriesAutoConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionManagerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionManagerConfiguration.java new file mode 100644 index 000000000000..53fb41d9954c --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionManagerConfiguration.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2024 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.data.neo4j; + +import org.neo4j.driver.Driver; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.neo4j.core.DatabaseSelectionProvider; +import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager; +import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension; +import org.springframework.transaction.TransactionManager; + +/** + * Configuration for a Neo4j-backed {@link TransactionManager}. + * + * @author Andy Wilkinson + */ +@Configuration(proxyBeanMethods = false) +class Neo4jTransactionManagerConfiguration { + + @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) + @ConditionalOnMissingBean(TransactionManager.class) + Neo4jTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider, + ObjectProvider optionalCustomizers) { + Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider); + optionalCustomizers.ifAvailable((customizer) -> customizer.customize((TransactionManager) transactionManager)); + return transactionManager; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionalComponentsConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionalComponentsConfiguration.java new file mode 100644 index 000000000000..d225e3cdbef3 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jTransactionalComponentsConfiguration.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012-2024 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.data.neo4j; + +import org.neo4j.driver.Driver; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.neo4j.core.DatabaseSelectionProvider; +import org.springframework.data.neo4j.core.Neo4jClient; +import org.springframework.data.neo4j.core.Neo4jOperations; +import org.springframework.data.neo4j.core.Neo4jTemplate; +import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext; +import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Neo4j components that require a {@link PlatformTransactionManager}. + * + * @author Andy Wilkinson + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnBean(PlatformTransactionManager.class) +class Neo4jTransactionalComponentsConfiguration { + + @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME) + @ConditionalOnMissingBean + Neo4jClient neo4jClient(Driver driver, DatabaseSelectionProvider databaseNameProvider) { + return Neo4jClient.create(driver, databaseNameProvider); + } + + @Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME) + @ConditionalOnMissingBean(Neo4jOperations.class) + Neo4jTemplate neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext) { + return new Neo4jTemplate(neo4jClient, neo4jMappingContext); + } + +} From a0cb2bdeaf6cb3c3cbef4a8aea37cc4ac0ae3b82 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 13 Feb 2024 17:34:47 +0000 Subject: [PATCH 083/182] Upgrade to Neo4j Java Driver 5.17.0 Closes gh-39534 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3a02e99f5d40..865e03e9f786 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1070,7 +1070,7 @@ bom { ] } } - library("Neo4j Java Driver", "5.15.0") { + library("Neo4j Java Driver", "5.17.0") { alignWithVersion { from "org.springframework.data:spring-data-neo4j" managedBy "Spring Data Bom" From 720e9cef162ab406e5d49648a55eb44fd212397e Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 13 Feb 2024 13:10:55 -0600 Subject: [PATCH 084/182] Make RestTemplateBuilder more compatible with RestClient.Builder When Spring Framework builds a `RestClient` from a `RestTemplate`, it will use any `UriTemplateHandler` that has been set on the `RestTemplate` if the provided `UriTemplateHandler` is also a `UriBuilderFactory`. Prior to this commit, Spring Boot's `RestTemplateBuilder#rootUri` set a `UriTemplateHandler` on the created `RestTemplate`, but it was not a `UriBuilderFactory` so `RestClient` would not consider it. With this commit, `RestTemplateBuilder#rootUri` sets a `UriTemplateHandler` that is also a `UriBuilderFactory` so that any root URI that is set on the `RestTemplateBuilder` will be applied to a `RestClient` also. Fixes gh-39317 --- ...estClientWithRestTemplateBuilderTests.java | 68 ++++++++++++++++++ .../RestClientWithRestTemplateTests.java | 72 +++++++++++++++++++ .../test/web/client/TestRestTemplate.java | 4 +- .../boot/web/client/RestTemplateBuilder.java | 10 ++- .../web/client/RootUriBuilderFactory.java | 65 +++++++++++++++++ .../web/client/RootUriTemplateHandler.java | 15 +++- .../web/client/RestTemplateBuilderTests.java | 6 +- .../client/RootUriBuilderFactoryTests.java | 43 +++++++++++ .../client/RootUriTemplateHandlerTests.java | 3 +- 9 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateBuilderTests.java create mode 100644 spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateTests.java create mode 100644 spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriBuilderFactory.java create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriBuilderFactoryTests.java diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateBuilderTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateBuilderTests.java new file mode 100644 index 000000000000..6a216e114e81 --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateBuilderTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2024 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.test.autoconfigure.web.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestClient.Builder; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Tests for building a {@link RestClient} from a {@link RestTemplateBuilder}. + * + * @author Scott Frederick + */ +class RestClientWithRestTemplateBuilderTests { + + @Test + void buildUsingRestTemplateBuilderRootUri() { + RestTemplate restTemplate = new RestTemplateBuilder().rootUri("https://resttemplate.example.com").build(); + RestClient.Builder builder = RestClient.builder(restTemplate); + RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + @Test + void buildUsingRestClientBuilderBaseUrl() { + RestTemplate restTemplate = new RestTemplateBuilder().build(); + RestClient.Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com"); + RestClient client = buildMockedClient(builder, "https://restclient.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + @Test + void buildRestTemplateBuilderRootUriAndRestClientBuilderBaseUrl() { + RestTemplate restTemplate = new RestTemplateBuilder().rootUri("https://resttemplate.example.com").build(); + RestClient.Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com"); + RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + private RestClient buildMockedClient(Builder builder, String url) { + MockRestServiceServer server = MockRestServiceServer.bindTo(builder).build(); + server.expect(requestTo(url)).andRespond(withSuccess()); + return builder.build(); + } + +} diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateTests.java new file mode 100644 index 000000000000..556991d9347f --- /dev/null +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/RestClientWithRestTemplateTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012-2024 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.test.autoconfigure.web.client; + +import org.junit.jupiter.api.Test; + +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestClient.Builder; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.DefaultUriBuilderFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Tests for building a {@link RestClient} from a {@link RestTemplate}. + * + * @author Scott Frederick + */ +class RestClientWithRestTemplateTests { + + @Test + void buildUsingRestTemplateUriTemplateHandler() { + RestTemplate restTemplate = new RestTemplate(); + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("https://resttemplate.example.com"); + restTemplate.setUriTemplateHandler(uriBuilderFactory); + Builder builder = RestClient.builder(restTemplate); + RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + @Test + void buildUsingRestClientBuilderBaseUrl() { + RestTemplate restTemplate = new RestTemplate(); + Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com"); + RestClient client = buildMockedClient(builder, "https://restclient.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + @Test + void buildUsingRestTemplateUriTemplateHandlerAndRestClientBuilderBaseUrl() { + RestTemplate restTemplate = new RestTemplate(); + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("https://resttemplate.example.com"); + restTemplate.setUriTemplateHandler(uriBuilderFactory); + Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com"); + RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test"); + assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue(); + } + + private RestClient buildMockedClient(Builder builder, String url) { + MockRestServiceServer server = MockRestServiceServer.bindTo(builder).build(); + server.expect(requestTo(url)).andRespond(withSuccess()); + return builder.build(); + } + +} diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java index 901b999bbf37..5f44bac53b47 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java @@ -171,8 +171,8 @@ public void setUriTemplateHandler(UriTemplateHandler handler) { } /** - * Returns the root URI applied by a {@link RootUriTemplateHandler} or {@code ""} if - * the root URI is not available. + * Returns the root URI applied by {@link RestTemplateBuilder#rootUri(String)} or + * {@code ""} if the root URI has not been applied. * @return the root URI */ public String getRootUri() { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java index a10a9ce10022..49d8ac59f60b 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RestTemplateBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -150,10 +150,8 @@ public RestTemplateBuilder detectRequestFactory(boolean detectRequestFactory) { /** * Set a root URL that should be applied to each request that starts with {@code '/'}. - * Since this works by adding a {@link UriTemplateHandler} to the - * {@link RestTemplate}, the root URL will only apply when {@code String} variants of - * the {@link RestTemplate} methods are used for specifying the request URL. See - * {@link RootUriTemplateHandler} for details. + * The root URL will only apply when {@code String} variants of the + * {@link RestTemplate} methods are used for specifying the request URL. * @param rootUri the root URI or {@code null} * @return a new builder instance */ @@ -639,7 +637,7 @@ public T configure(T restTemplate) { restTemplate.setErrorHandler(this.errorHandler); } if (this.rootUri != null) { - RootUriTemplateHandler.addTo(restTemplate, this.rootUri); + RootUriBuilderFactory.applyTo(restTemplate, this.rootUri); } restTemplate.getInterceptors().addAll(this.interceptors); if (!CollectionUtils.isEmpty(this.customizers)) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriBuilderFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriBuilderFactory.java new file mode 100644 index 000000000000..da2945a7f475 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriBuilderFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-2024 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.web.client; + +import org.springframework.util.Assert; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriBuilderFactory; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriTemplateHandler; + +/** + * {@link UriBuilderFactory} to set the root for URI that starts with {@code '/'}. + * + * @author Scott Frederick + * @since 3.2.3 + */ +public class RootUriBuilderFactory extends RootUriTemplateHandler implements UriBuilderFactory { + + @SuppressWarnings("removal") + RootUriBuilderFactory(String rootUri) { + super(rootUri); + } + + @SuppressWarnings("removal") + RootUriBuilderFactory(String rootUri, UriTemplateHandler delegate) { + super(rootUri, delegate); + } + + @Override + public UriBuilder uriString(String uriTemplate) { + return UriComponentsBuilder.fromUriString(apply(uriTemplate)); + } + + @Override + public UriBuilder builder() { + return UriComponentsBuilder.newInstance(); + } + + /** + * Apply a {@link RootUriBuilderFactory} instance to the given {@link RestTemplate}. + * @param restTemplate the {@link RestTemplate} to add the builder factory to + * @param rootUri the root URI + */ + static void applyTo(RestTemplate restTemplate, String rootUri) { + Assert.notNull(restTemplate, "RestTemplate must not be null"); + RootUriBuilderFactory handler = new RootUriBuilderFactory(rootUri, restTemplate.getUriTemplateHandler()); + restTemplate.setUriTemplateHandler(handler); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriTemplateHandler.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriTemplateHandler.java index e52c59b95fe6..4a007a6fcaa7 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriTemplateHandler.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/RootUriTemplateHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2024 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,6 +30,7 @@ * {@link UriTemplateHandler} to set the root for URI that starts with {@code '/'}. * * @author Phillip Webb + * @author Scott Frederick * @since 1.4.0 */ public class RootUriTemplateHandler implements UriTemplateHandler { @@ -47,7 +48,9 @@ protected RootUriTemplateHandler(UriTemplateHandler handler) { /** * Create a new {@link RootUriTemplateHandler} instance. * @param rootUri the root URI to be used to prefix relative URLs + * @deprecated since 3.2.3 for removal in 3.4.0, with no replacement */ + @Deprecated(since = "3.2.3", forRemoval = true) public RootUriTemplateHandler(String rootUri) { this(rootUri, new DefaultUriBuilderFactory()); } @@ -55,8 +58,10 @@ public RootUriTemplateHandler(String rootUri) { /** * Create a new {@link RootUriTemplateHandler} instance. * @param rootUri the root URI to be used to prefix relative URLs - * @param handler the delegate handler + * @param handler the handler handler + * @deprecated since 3.2.3 for removal in 3.4.0, with no replacement */ + @Deprecated(since = "3.2.3", forRemoval = true) public RootUriTemplateHandler(String rootUri, UriTemplateHandler handler) { Assert.notNull(rootUri, "RootUri must not be null"); Assert.notNull(handler, "Handler must not be null"); @@ -74,7 +79,7 @@ public URI expand(String uriTemplate, Object... uriVariables) { return this.handler.expand(apply(uriTemplate), uriVariables); } - private String apply(String uriTemplate) { + String apply(String uriTemplate) { if (StringUtils.startsWithIgnoreCase(uriTemplate, "/")) { return getRootUri() + uriTemplate; } @@ -91,7 +96,9 @@ public String getRootUri() { * @param wrapper the wrapper to apply to the delegate URI template handler * @return the new handler * @since 2.3.10 + * @deprecated since 3.2.3 for removal in 3.4.0, with no replacement */ + @Deprecated(since = "3.2.3", forRemoval = true) public RootUriTemplateHandler withHandlerWrapper(Function wrapper) { return new RootUriTemplateHandler(getRootUri(), wrapper.apply(this.handler)); } @@ -101,7 +108,9 @@ public RootUriTemplateHandler withHandlerWrapper(Function { assertThat(restTemplate.getInterceptors()).hasSize(1); assertThat(restTemplate.getMessageConverters()).contains(this.messageConverter); - assertThat(restTemplate.getUriTemplateHandler()).isInstanceOf(RootUriTemplateHandler.class); + assertThat(restTemplate.getUriTemplateHandler()).isInstanceOf(RootUriBuilderFactory.class); assertThat(restTemplate.getErrorHandler()).isEqualTo(errorHandler); ClientHttpRequestFactory actualRequestFactory = restTemplate.getRequestFactory(); assertThat(actualRequestFactory).isInstanceOf(InterceptingClientHttpRequestFactory.class); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriBuilderFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriBuilderFactoryTests.java new file mode 100644 index 000000000000..1a77773cd742 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriBuilderFactoryTests.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2024 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.web.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.jupiter.api.Test; + +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriBuilderFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link RootUriBuilderFactory}. + * + * @author Scott Frederick + */ +class RootUriBuilderFactoryTests { + + @Test + void uriStringPrefixesRoot() throws URISyntaxException { + UriBuilderFactory builderFactory = new RootUriBuilderFactory("https://example.com"); + UriBuilder builder = builderFactory.uriString("/hello"); + assertThat(builder.build()).isEqualTo(new URI("https://example.com/hello")); + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriTemplateHandlerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriTemplateHandlerTests.java index 2e8140008920..56288dc3d71f 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriTemplateHandlerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/client/RootUriTemplateHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -43,6 +43,7 @@ * @author Phillip Webb */ @ExtendWith(MockitoExtension.class) +@SuppressWarnings("removal") class RootUriTemplateHandlerTests { private URI uri; From 256f9fe83af13066725802dd692de6dfe8dd046f Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 9 Feb 2024 18:25:51 +0000 Subject: [PATCH 085/182] Only configure WebFlux blocking executor when using virtual threads Fixes gh-39469 --- .../reactive/WebFluxAutoConfiguration.java | 12 ++++-- .../WebFluxAutoConfigurationTests.java | 38 ++++++++++++++----- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index e9ebef362499..cab4dd72b436 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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,7 @@ import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration; import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders; +import org.springframework.boot.autoconfigure.thread.Threading; import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.autoconfigure.validation.ValidatorAdapter; import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain; @@ -55,6 +56,7 @@ import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.format.FormatterRegistry; import org.springframework.format.support.FormattingConversionService; @@ -149,6 +151,8 @@ public static class WebFluxConfig implements WebFluxConfigurer { private static final Log logger = LogFactory.getLog(WebFluxConfig.class); + private final Environment environment; + private final Resources resourceProperties; private final WebFluxProperties webFluxProperties; @@ -163,11 +167,12 @@ public static class WebFluxConfig implements WebFluxConfigurer { private final ObjectProvider viewResolvers; - public WebFluxConfig(WebProperties webProperties, WebFluxProperties webFluxProperties, + public WebFluxConfig(Environment environment, WebProperties webProperties, WebFluxProperties webFluxProperties, ListableBeanFactory beanFactory, ObjectProvider resolvers, ObjectProvider codecCustomizers, ObjectProvider resourceHandlerRegistrationCustomizer, ObjectProvider viewResolvers) { + this.environment = environment; this.resourceProperties = webProperties.getResources(); this.webFluxProperties = webFluxProperties; this.beanFactory = beanFactory; @@ -189,7 +194,8 @@ public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { @Override public void configureBlockingExecution(BlockingExecutionConfigurer configurer) { - if (this.beanFactory.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) { + if (Threading.VIRTUAL.isActive(this.environment) && this.beanFactory + .containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) { Object taskExecutor = this.beanFactory .getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME); if (taskExecutor instanceof AsyncTaskExecutor asyncTaskExecutor) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index cf40c58a52c9..53731f72fcfb 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -39,6 +39,8 @@ import org.assertj.core.api.Assertions; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; +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.ValueSource; @@ -687,8 +689,20 @@ void problemDetailsExceptionHandlerIsOrderedAt0() { } @Test - void asyncTaskExecutorWithApplicationTaskExecutor() { + void asyncTaskExecutorWithPlatformThreadsAndApplicationTaskExecutor() { this.contextRunner.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class)) + .run((context) -> { + assertThat(context).hasSingleBean(AsyncTaskExecutor.class); + assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor") + .isNull(); + }); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void asyncTaskExecutorWithVirtualThreadsAndApplicationTaskExecutor() { + this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true") + .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class)) .run((context) -> { assertThat(context).hasSingleBean(AsyncTaskExecutor.class); assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor") @@ -697,8 +711,10 @@ void asyncTaskExecutorWithApplicationTaskExecutor() { } @Test - void asyncTaskExecutorWithNonMatchApplicationTaskExecutorBean() { - this.contextRunner.withUserConfiguration(CustomApplicationTaskExecutorConfig.class) + @EnabledForJreRange(min = JRE.JAVA_21) + void asyncTaskExecutorWithVirtualThreadsAndNonMatchApplicationTaskExecutorBean() { + this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true") + .withUserConfiguration(CustomApplicationTaskExecutorConfig.class) .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class)) .run((context) -> { assertThat(context).doesNotHaveBean(AsyncTaskExecutor.class); @@ -708,8 +724,10 @@ void asyncTaskExecutorWithNonMatchApplicationTaskExecutorBean() { } @Test - void asyncTaskExecutorWithWebFluxConfigurerCanOverrideExecutor() { - this.contextRunner.withUserConfiguration(CustomAsyncTaskExecutorConfigurer.class) + @EnabledForJreRange(min = JRE.JAVA_21) + void asyncTaskExecutorWithVirtualThreadsAndWebFluxConfigurerCanOverrideExecutor() { + this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true") + .withUserConfiguration(CustomAsyncTaskExecutorConfigurer.class) .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class)) .run((context) -> assertThat(context.getBean(RequestMappingHandlerAdapter.class)) .extracting("scheduler.executor") @@ -717,13 +735,15 @@ void asyncTaskExecutorWithWebFluxConfigurerCanOverrideExecutor() { } @Test - void asyncTaskExecutorWithCustomNonApplicationTaskExecutor() { - this.contextRunner.withUserConfiguration(CustomAsyncTaskExecutorConfig.class) + @EnabledForJreRange(min = JRE.JAVA_21) + void asyncTaskExecutorWithVirtualThreadsAndCustomNonApplicationTaskExecutor() { + this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true") + .withUserConfiguration(CustomAsyncTaskExecutorConfig.class) .withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class)) .run((context) -> { assertThat(context).hasSingleBean(AsyncTaskExecutor.class); assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor") - .isNotSameAs(context.getBean("customTaskExecutor")); + .isNull(); }); } From 144ed54d56ebe45c0cdd818a27b485f377ed7ccd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 19:11:09 +0000 Subject: [PATCH 086/182] Bump gradle/wrapper-validation-action from 2.0.0 to 2.1.1 Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 2.0.0 to 2.1.1. - [Release notes](https://github.com/gradle/wrapper-validation-action/releases) - [Commits](https://github.com/gradle/wrapper-validation-action/compare/27152f6fa06a6b8062ef7195c795692e51fc2c81...699bb18358f12c5b78b37bb0111d3a0e2276e0e2) --- updated-dependencies: - dependency-name: gradle/wrapper-validation-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] See gh-39528 --- .github/workflows/build-pull-request.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 6a8d68f0cc48..00061b14149f 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@27152f6fa06a6b8062ef7195c795692e51fc2c81 + uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 - name: Set up Gradle uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index c4c588261113..0a3f50c1f72a 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -10,4 +10,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@27152f6fa06a6b8062ef7195c795692e51fc2c81 + - uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 From 5bc4bdd1de52dc6351d11c52c08e3a50ba25e0a8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 14:53:15 +0000 Subject: [PATCH 087/182] Test Gradle plugin against Gradle 8.6 Closes gh-39548 --- .../boot/testsupport/gradle/testkit/GradleVersions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java index 0a4049a69505..8aa1fc3cf9d8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-test-support/src/main/java/org/springframework/boot/testsupport/gradle/testkit/GradleVersions.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -35,9 +35,9 @@ private GradleVersions() { @SuppressWarnings("UnstableApiUsage") public static List allCompatible() { if (isJavaVersion(JavaVersion.VERSION_20)) { - return Arrays.asList("8.1.1", "8.5"); + return Arrays.asList("8.1.1", "8.6"); } - return Arrays.asList("7.5.1", GradleVersion.current().getVersion(), "8.0.2", "8.5"); + return Arrays.asList("7.5.1", GradleVersion.current().getVersion(), "8.0.2", "8.6"); } public static String minimumCompatible() { From f7aef186bd9199ffe5e71d76d908936f9dafcb17 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:05:23 +0000 Subject: [PATCH 088/182] Upgrade to Neo4j Java Driver 5.17.0 Closes gh-39551 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3b8a332102a9..0a466b95b516 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1050,7 +1050,7 @@ bom { ] } } - library("Neo4j Java Driver", "5.15.0") { + library("Neo4j Java Driver", "5.17.0") { alignWithVersion { from "org.springframework.data:spring-data-neo4j" managedBy "Spring Data Bom" From 5f004d752dfcb492d4e5b7c3f301872f92a68251 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:54:41 +0000 Subject: [PATCH 089/182] Upgrade to Dropwizard Metrics 4.2.25 Closes gh-39553 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0a466b95b516..abb354a12708 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -240,7 +240,7 @@ bom { ] } } - library("Dropwizard Metrics", "4.2.23") { + library("Dropwizard Metrics", "4.2.25") { group("io.dropwizard.metrics") { imports = [ "metrics-bom" From fe384576a1d0dce5715582602d70daaf3a9df1a3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:54:45 +0000 Subject: [PATCH 090/182] Upgrade to Groovy 4.0.18 Closes gh-39554 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index abb354a12708..0e4a06b44974 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -327,7 +327,7 @@ bom { ] } } - library("Groovy", "4.0.17") { + library("Groovy", "4.0.18") { group("org.apache.groovy") { imports = [ "groovy-bom" From 2507b5e9e2ec2ff8616102597e26f0f53a10885d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:54:50 +0000 Subject: [PATCH 091/182] Upgrade to Hibernate 6.2.22.Final Closes gh-39555 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0e4a06b44974..16d40b776bd2 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -365,7 +365,7 @@ bom { ] } } - library("Hibernate", "6.2.20.Final") { + library("Hibernate", "6.2.22.Final") { group("org.hibernate.orm") { modules = [ "hibernate-agroal", From 34946b215247f537889929fabb0b2b2bf5a3ac6e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:54:55 +0000 Subject: [PATCH 092/182] Upgrade to Infinispan 14.0.24.Final Closes gh-39556 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 16d40b776bd2..2cb610e2fefb 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -453,7 +453,7 @@ bom { ] } } - library("Infinispan", "14.0.21.Final") { + library("Infinispan", "14.0.24.Final") { group("org.infinispan") { imports = [ "infinispan-bom" From b524abbbf07f8d28039866b2bb35b5b21af5006e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:54:59 +0000 Subject: [PATCH 093/182] Upgrade to Janino 3.1.12 Closes gh-39557 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 2cb610e2fefb..31e407388cfc 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -594,7 +594,7 @@ bom { ] } } - library("Janino", "3.1.11") { + library("Janino", "3.1.12") { group("org.codehaus.janino") { modules = [ "commons-compiler", From 15fc9f2377c3d5027257cc7c8b6913aa2db72a22 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:04 +0000 Subject: [PATCH 094/182] Upgrade to Jetty Reactive HTTPClient 3.0.12 Closes gh-39558 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 31e407388cfc..a1b31682478a 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -659,7 +659,7 @@ bom { ] } } - library("Jetty Reactive HTTPClient", "3.0.11") { + library("Jetty Reactive HTTPClient", "3.0.12") { group("org.eclipse.jetty") { modules = [ "jetty-reactive-httpclient" From 1d6712431b62ea320eda9d615c60bede024c38e2 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:09 +0000 Subject: [PATCH 095/182] Upgrade to Jetty 11.0.20 Closes gh-39559 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a1b31682478a..060eaabbf6ba 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -666,7 +666,7 @@ bom { ] } } - library("Jetty", "11.0.19") { + library("Jetty", "11.0.20") { group("org.eclipse.jetty") { imports = [ "jetty-bom" From 017bcf0d79133983ee2fe346f7e966d7d394a830 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:13 +0000 Subject: [PATCH 096/182] Upgrade to jOOQ 3.18.10 Closes gh-39560 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 060eaabbf6ba..d642279ea5e0 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -680,7 +680,7 @@ bom { ] } } - library("jOOQ", "3.18.9") { + library("jOOQ", "3.18.10") { group("org.jooq") { modules = [ "jooq", From ff9888be3c2e8763f631adf159a2617ae7dd24cf Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:14 +0000 Subject: [PATCH 097/182] Upgrade to Micrometer 1.11.9 Closes gh-39454 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d642279ea5e0..57cba3d539e3 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -975,7 +975,7 @@ bom { ] } } - library("Micrometer", "1.11.9-SNAPSHOT") { + library("Micrometer", "1.11.9") { considerSnapshots() group("io.micrometer") { modules = [ From 2839f0c4437b3fc6ed88d516e477fcbe9c5904c4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:15 +0000 Subject: [PATCH 098/182] Upgrade to Micrometer Tracing 1.1.10 Closes gh-39455 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 57cba3d539e3..2dab6c7a9f83 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -988,7 +988,7 @@ bom { ] } } - library("Micrometer Tracing", "1.1.10-SNAPSHOT") { + library("Micrometer Tracing", "1.1.10") { considerSnapshots() calendarName = "Tracing" group("io.micrometer") { From ba15d8daa4b1ef2182f151a969bbb96fa4a2398d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:19 +0000 Subject: [PATCH 099/182] Upgrade to Netty 4.1.107.Final Closes gh-39561 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 2dab6c7a9f83..a8f6f52d5e6d 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1061,7 +1061,7 @@ bom { ] } } - library("Netty", "4.1.105.Final") { + library("Netty", "4.1.107.Final") { group("io.netty") { imports = [ "netty-bom" From 642517a27ad601896f5e8111fed5a0812ad8d7ea Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:24 +0000 Subject: [PATCH 100/182] Upgrade to SLF4J 2.0.12 Closes gh-39562 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a8f6f52d5e6d..44a1df587e01 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1358,7 +1358,7 @@ bom { ] } } - library("SLF4J", "2.0.11") { + library("SLF4J", "2.0.12") { group("org.slf4j") { modules = [ "jcl-over-slf4j", From 0f341f4cb00492b8cdd59153144c4249ed656bcd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 15:55:28 +0000 Subject: [PATCH 101/182] Upgrade to Undertow 2.3.11.Final Closes gh-39563 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 44a1df587e01..e0b1365125de 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1580,7 +1580,7 @@ bom { ] } } - library("Undertow", "2.3.10.Final") { + library("Undertow", "2.3.11.Final") { group("io.undertow") { modules = [ "undertow-core", From 0ba1496f61c418abb9008d14c3c0bfa4adc2024b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:24 +0000 Subject: [PATCH 102/182] Upgrade to Commons Codec 1.16.1 Closes gh-39566 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d1786b540b68..d1f14de5e3dc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 assertjVersion=3.24.2 -commonsCodecVersion=1.16.0 +commonsCodecVersion=1.16.1 commonsCompressVersion=1.21 hamcrestVersion=2.2 jacksonVersion=2.15.3 From ec5b259381daf282a163f468a90717bc007d259d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:29 +0000 Subject: [PATCH 103/182] Upgrade to Dropwizard Metrics 4.2.25 Closes gh-39567 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 865e03e9f786..c498d93bcb76 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -247,7 +247,7 @@ bom { ] } } - library("Dropwizard Metrics", "4.2.23") { + library("Dropwizard Metrics", "4.2.25") { group("io.dropwizard.metrics") { imports = [ "metrics-bom" From c0ec714e0a290923ce8503bd6a246240763f9500 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:33 +0000 Subject: [PATCH 104/182] Upgrade to Groovy 4.0.18 Closes gh-39568 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c498d93bcb76..f675f1149cad 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -339,7 +339,7 @@ bom { ] } } - library("Groovy", "4.0.17") { + library("Groovy", "4.0.18") { group("org.apache.groovy") { imports = [ "groovy-bom" From 7dc24370c6538e242aa0eaca59372ccacdd1af50 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:38 +0000 Subject: [PATCH 105/182] Upgrade to Hibernate 6.4.4.Final Closes gh-39569 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f675f1149cad..aa43949e9c54 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -377,7 +377,7 @@ bom { ] } } - library("Hibernate", "6.4.1.Final") { + library("Hibernate", "6.4.4.Final") { group("org.hibernate.orm") { modules = [ "hibernate-agroal", From 4ee4215c8b49e0d40fe97ee86f77d1fa20c290fd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:43 +0000 Subject: [PATCH 106/182] Upgrade to Infinispan 14.0.24.Final Closes gh-39570 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index aa43949e9c54..a98b6069ead9 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -465,7 +465,7 @@ bom { ] } } - library("Infinispan", "14.0.21.Final") { + library("Infinispan", "14.0.24.Final") { group("org.infinispan") { imports = [ "infinispan-bom" From 6ea6aa42f7b3ecae4f634e79b344632f0ee5d7ed Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:47 +0000 Subject: [PATCH 107/182] Upgrade to Janino 3.1.12 Closes gh-39571 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a98b6069ead9..f33dc42d82f0 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -606,7 +606,7 @@ bom { ] } } - library("Janino", "3.1.11") { + library("Janino", "3.1.12") { group("org.codehaus.janino") { modules = [ "commons-compiler", From 3a9987371cc60fd13cea98d7c2c2e412362db9ab Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:52 +0000 Subject: [PATCH 108/182] Upgrade to Jetty Reactive HTTPClient 4.0.3 Closes gh-39572 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f33dc42d82f0..a834df1674ac 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -671,7 +671,7 @@ bom { ] } } - library("Jetty Reactive HTTPClient", "4.0.1") { + library("Jetty Reactive HTTPClient", "4.0.3") { group("org.eclipse.jetty") { modules = [ "jetty-reactive-httpclient" From 1d4f0e78e6a7e2296bd07330ea737de579489cea Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:58:57 +0000 Subject: [PATCH 109/182] Upgrade to Jetty 12.0.6 Closes gh-39573 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a834df1674ac..e59982595701 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -678,7 +678,7 @@ bom { ] } } - library("Jetty", "12.0.5") { + library("Jetty", "12.0.6") { group("org.eclipse.jetty.ee10") { imports = [ "jetty-ee10-bom" From 5c6f200b85a44deff1117a8f75bc877041f5e7ed Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:01 +0000 Subject: [PATCH 110/182] Upgrade to jOOQ 3.18.10 Closes gh-39574 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e59982595701..4516c4ae8075 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -697,7 +697,7 @@ bom { ] } } - library("jOOQ", "3.18.9") { + library("jOOQ", "3.18.10") { group("org.jooq") { modules = [ "jooq", From d16c3db912be922d0714afbe9cf868f3481c3ac3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:06 +0000 Subject: [PATCH 111/182] Upgrade to JUnit Jupiter 5.10.2 Closes gh-39575 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d1f14de5e3dc..7121b3e74eec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ commonsCodecVersion=1.16.1 commonsCompressVersion=1.21 hamcrestVersion=2.2 jacksonVersion=2.15.3 -junitJupiterVersion=5.10.1 +junitJupiterVersion=5.10.2 kotlinVersion=1.9.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 From a7d78aee8bbe9241375ddffb5f840ae7a6c20a50 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:06 +0000 Subject: [PATCH 112/182] Upgrade to Micrometer 1.12.3 Closes gh-39474 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 4516c4ae8075..0bee836f9532 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -995,7 +995,7 @@ bom { ] } } - library("Micrometer", "1.12.3-SNAPSHOT") { + library("Micrometer", "1.12.3") { considerSnapshots() group("io.micrometer") { modules = [ From 6536ee973a5a8d59c23348667df46bfbdcc893db Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:07 +0000 Subject: [PATCH 113/182] Upgrade to Micrometer Tracing 1.2.3 Closes gh-39475 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0bee836f9532..89f6485d43e5 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1008,7 +1008,7 @@ bom { ] } } - library("Micrometer Tracing", "1.2.3-SNAPSHOT") { + library("Micrometer Tracing", "1.2.3") { considerSnapshots() calendarName = "Tracing" group("io.micrometer") { From a61a7b9d169ce7324ee20ee64ae7eb11aded8d3a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:12 +0000 Subject: [PATCH 114/182] Upgrade to Netty 4.1.107.Final Closes gh-39576 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 89f6485d43e5..30b3ddba0efd 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1081,7 +1081,7 @@ bom { ] } } - library("Netty", "4.1.105.Final") { + library("Netty", "4.1.107.Final") { group("io.netty") { imports = [ "netty-bom" From 24572e46c9854b6e6a5e731c648a9d3b2ab701fc Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:16 +0000 Subject: [PATCH 115/182] Upgrade to SLF4J 2.0.12 Closes gh-39577 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 30b3ddba0efd..1382fdb0f76c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1471,7 +1471,7 @@ bom { ] } } - library("SLF4J", "2.0.11") { + library("SLF4J", "2.0.12") { group("org.slf4j") { modules = [ "jcl-over-slf4j", From 90e46b941536d1d09cb95cecb0ee15917a59b7c6 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:23 +0000 Subject: [PATCH 116/182] Upgrade to Testcontainers 1.19.5 Closes gh-39578 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 1382fdb0f76c..4b38cf066121 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1641,7 +1641,7 @@ bom { ] } } - library("Testcontainers", "1.19.4") { + library("Testcontainers", "1.19.5") { group("org.testcontainers") { imports = [ "testcontainers-bom" From 6be9fdaeec3c4584d5a438cb6833513e3d83a9f8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 17:59:28 +0000 Subject: [PATCH 117/182] Upgrade to Undertow 2.3.11.Final Closes gh-39579 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 4b38cf066121..67314a4265cb 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1701,7 +1701,7 @@ bom { ] } } - library("Undertow", "2.3.10.Final") { + library("Undertow", "2.3.11.Final") { group("io.undertow") { modules = [ "undertow-core", From 71abc9d6b7e60d1e67fdea4d8ebfb5c095c1118b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 14 Feb 2024 18:58:19 +0000 Subject: [PATCH 118/182] fixup! Upgrade to Testcontainers 1.19.5 --- .../boot/image/assertions/ImageAssert.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java index fc5f9509412b..ce326c1702ba 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/assertions/ImageAssert.java @@ -80,12 +80,12 @@ public ListAssert entries() { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { if (!entry.isDirectory()) { entryNames.add(entry.getName().replaceFirst("^/workspace/", "")); } - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } } @@ -101,7 +101,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { this.actual.writeTo(out); try (TarArchiveInputStream in = new TarArchiveInputStream( new ByteArrayInputStream(out.toByteArray()))) { - TarArchiveEntry entry = in.getNextEntry(); + TarArchiveEntry entry = in.getNextTarEntry(); while (entry != null) { if (entry.getName().equals(name)) { ByteArrayOutputStream entryOut = new ByteArrayOutputStream(); @@ -109,7 +109,7 @@ public void jsonEntry(String name, Consumer assertConsumer) { assertConsumer.accept(new JsonContentAssert(LayerContentAssert.class, entryOut.toString())); return; } - entry = in.getNextEntry(); + entry = in.getNextTarEntry(); } } failWithMessage("Expected JSON entry '%s' in layer with digest '%s'", name, this.actual.getId()); From 3befeb2d7e64a049adfc8b92d88319ad41afb0f9 Mon Sep 17 00:00:00 2001 From: gdmrw Date: Wed, 14 Feb 2024 03:30:03 -0800 Subject: [PATCH 119/182] Add smoke test for InfoContributor See gh-39544 --- .../actuator/SampleActuatorApplicationTests.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java index 8ddd0cefe697..360e0719a5a1 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java @@ -177,6 +177,18 @@ void testLegacyHyphen() { assertThat(entity.getBody()).contains(entry("legacy", "legacy")); } + @Test + @SuppressWarnings("unchecked") + void testInfo() { + ResponseEntity> entity = asMapEntity( + this.restTemplate.withBasicAuth("user", "password").getForEntity("/actuator/info", Map.class)); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getBody()).containsKey("build"); + Map body = entity.getBody(); + Map example = (Map) body.get("example"); + assertThat(example).containsEntry("someKey", "someValue"); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) static ResponseEntity> asMapEntity(ResponseEntity entity) { return (ResponseEntity) entity; From 7ade54d3040f90800ca80a271b8b63894845bdda Mon Sep 17 00:00:00 2001 From: lukasdooo Date: Thu, 15 Feb 2024 20:46:21 +0100 Subject: [PATCH 120/182] Document default value for show-value configuration properties See gh-39589 --- .../additional-spring-configuration-metadata.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 c13d14622e4b..4b874c7de734 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 @@ -30,6 +30,14 @@ "description": "Whether to enable default metrics exporters.", "defaultValue": true }, + { + "name": "management.endpoint.configprops.show-values", + "defaultValue": "never" + }, + { + "name": "management.endpoint.env.show-values", + "defaultValue": "never" + }, { "name": "management.endpoint.health.probes.add-additional-paths", "type": "java.lang.Boolean", @@ -95,6 +103,10 @@ "health" ] }, + { + "name": "management.endpoint.quartz.show-values", + "defaultValue": "never" + }, { "name": "management.ganglia.metrics.export.addressing-mode", "defaultValue": "multicast" From e2b29dc9cbd576c4e2b7602bad9bb2e6d0d57473 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Fri, 16 Feb 2024 09:24:32 +0100 Subject: [PATCH 121/182] Polish "Document default value for show-value configuration properties" See gh-39589 --- .../additional-spring-configuration-metadata.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 4b874c7de734..7dfd03e8103a 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 @@ -69,6 +69,10 @@ "description": "Whether to validate health group membership on startup. Validation fails if a group includes or excludes a health contributor that does not exist.", "defaultValue": true }, + { + "name": "management.endpoint.quartz.show-values", + "defaultValue": "never" + }, { "name": "management.endpoints.enabled-by-default", "type": "java.lang.Boolean", @@ -103,10 +107,6 @@ "health" ] }, - { - "name": "management.endpoint.quartz.show-values", - "defaultValue": "never" - }, { "name": "management.ganglia.metrics.export.addressing-mode", "defaultValue": "multicast" From 8fee77761d99dd17ddee17a73fb2228de6b1ee49 Mon Sep 17 00:00:00 2001 From: junhyung Date: Sun, 28 Jan 2024 01:47:08 +0900 Subject: [PATCH 122/182] Change ConcurrentReferenceCachingMetadataReaderFactory to use application's resource loader See gh-39321 --- .../SharedMetadataReaderFactoryContextInitializer.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java index 8ffcaa58e77b..bdbd781ed1d1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SharedMetadataReaderFactoryContextInitializer.java @@ -21,7 +21,6 @@ import org.springframework.aot.AotDetector; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter; @@ -38,11 +37,13 @@ import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; +import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReaderFactory; @@ -187,14 +188,14 @@ private void configureConfigurationClassPostProcessor(ConfigurationClassPostProc * {@link FactoryBean} to create the shared {@link MetadataReaderFactory}. */ static class SharedMetadataReaderFactoryBean - implements FactoryBean, BeanClassLoaderAware, + implements FactoryBean, ResourceLoaderAware, ApplicationListener { private ConcurrentReferenceCachingMetadataReaderFactory metadataReaderFactory; @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.metadataReaderFactory = new ConcurrentReferenceCachingMetadataReaderFactory(classLoader); + public void setResourceLoader(ResourceLoader resourceLoader) { + this.metadataReaderFactory = new ConcurrentReferenceCachingMetadataReaderFactory(resourceLoader); } @Override From 59693f2b12e4ea7cc7081cda45ebaab72fcb2dda Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 16 Feb 2024 15:03:18 +0100 Subject: [PATCH 123/182] Move "micrometer.observations.*" configuration properties This commit moves the "micrometer.observations.*" configuration properties to "management.observations.*" namespace, as it was introduced in the wrong namespace initially. The former configuration property is deprecated and will be removed in a future version. Fixes gh-39600 --- .../MetricsAspectsAutoConfiguration.java | 23 ++++++++++++++++++- .../MicrometerTracingAutoConfiguration.java | 22 +++++++++++++++++- ...itional-spring-configuration-metadata.json | 12 ++++++++-- .../MetricsAspectsAutoConfigurationTests.java | 13 ++++++++++- ...crometerTracingAutoConfigurationTests.java | 17 +++++++++++--- .../src/docs/asciidoc/actuator/metrics.adoc | 2 +- .../docs/asciidoc/actuator/observability.adoc | 2 +- 7 files changed, 81 insertions(+), 10 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration.java index 1541778479a9..959789adfd50 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration.java @@ -23,13 +23,16 @@ import org.aspectj.weaver.Advice; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAspectsAutoConfiguration.ObservationAnnotationsEnabledCondition; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; /** * {@link EnableAutoConfiguration Auto-configuration} for Micrometer-based metrics @@ -40,7 +43,7 @@ */ @AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class }) @ConditionalOnClass({ MeterRegistry.class, Advice.class }) -@ConditionalOnProperty(prefix = "micrometer.observations.annotations", name = "enabled", havingValue = "true") +@Conditional(ObservationAnnotationsEnabledCondition.class) @ConditionalOnBean(MeterRegistry.class) public class MetricsAspectsAutoConfiguration { @@ -59,4 +62,22 @@ TimedAspect timedAspect(MeterRegistry registry, return timedAspect; } + static final class ObservationAnnotationsEnabledCondition extends AnyNestedCondition { + + ObservationAnnotationsEnabledCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty(prefix = "micrometer.observations.annotations", name = "enabled", havingValue = "true") + static class MicrometerObservationsEnabledCondition { + + } + + @ConditionalOnProperty(prefix = "management.observations.annotations", name = "enabled", havingValue = "true") + static class ManagementObservationsEnabledCondition { + + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfiguration.java index 1ef058236f8a..b53699f2c1f4 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfiguration.java @@ -32,11 +32,13 @@ import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; @@ -97,7 +99,7 @@ public PropagatingReceiverTracingObservationHandler propagatingReceiverTracin @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Advice.class) - @ConditionalOnProperty(prefix = "micrometer.observations.annotations", name = "enabled", havingValue = "true") + @Conditional(ObservationAnnotationsEnabledCondition.class) static class SpanAspectConfiguration { @Bean @@ -124,4 +126,22 @@ SpanAspect spanAspect(MethodInvocationProcessor methodInvocationProcessor) { } + static final class ObservationAnnotationsEnabledCondition extends AnyNestedCondition { + + ObservationAnnotationsEnabledCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty(prefix = "micrometer.observations.annotations", name = "enabled", havingValue = "true") + static class MicrometerObservationsEnabledCondition { + + } + + @ConditionalOnProperty(prefix = "management.observations.annotations", name = "enabled", havingValue = "true") + static class ManagementObservationsEnabledCondition { + + } + + } + } 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 77d1b96acf9d..f5cac72f8ac0 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 @@ -2073,6 +2073,12 @@ "level": "error" } }, + { + "name": "management.observations.annotations.enabled", + "type": "java.lang.Boolean", + "description": "Whether auto-configuration of Micrometer annotations is enabled.", + "defaultValue": false + }, { "name": "management.otlp.metrics.export.base-time-unit", "defaultValue": "milliseconds" @@ -2245,8 +2251,10 @@ { "name": "micrometer.observations.annotations.enabled", "type": "java.lang.Boolean", - "description": "Whether auto-configuration of Micrometer annotations is enabled.", - "defaultValue": false + "deprecation": { + "level": "error", + "replacement": "management.observations.annotations.enabled" + } } ], "hints": [ diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfigurationTests.java index d2ecaf6f06d2..5371146e0f42 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfigurationTests.java @@ -41,7 +41,7 @@ class MetricsAspectsAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple()) - .withPropertyValues("micrometer.observations.annotations.enabled=true") + .withPropertyValues("management.observations.annotations.enabled=true") .withConfiguration(AutoConfigurations.of(MetricsAspectsAutoConfiguration.class)); @Test @@ -54,6 +54,17 @@ void shouldNotConfigureAspectsByDefault() { }); } + @Test + void shouldConfigureAspectsWithLegacyProperty() { + new ApplicationContextRunner().with(MetricsRun.simple()) + .withConfiguration(AutoConfigurations.of(MetricsAspectsAutoConfiguration.class)) + .withPropertyValues("micrometer.observations.annotations.enabled=true") + .run((context) -> { + assertThat(context).hasSingleBean(CountedAspect.class); + assertThat(context).hasSingleBean(TimedAspect.class); + }); + } + @Test void shouldConfigureAspects() { this.contextRunner.run((context) -> { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfigurationTests.java index f671d494159e..5fb5e7d6af8f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/MicrometerTracingAutoConfigurationTests.java @@ -52,13 +52,12 @@ class MicrometerTracingAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("micrometer.observations.annotations.enabled=true") + .withPropertyValues("management.observations.annotations.enabled=true") .withConfiguration(AutoConfigurations.of(MicrometerTracingAutoConfiguration.class)); @Test void shouldSupplyBeans() { this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) - .withPropertyValues("micrometer.observations.annotations.enabled=true") .run((context) -> { assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class); assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class); @@ -133,7 +132,7 @@ void shouldNotSupplyBeansIfTracerIsMissing() { @Test void shouldNotSupplyAspectBeansIfPropertyIsDisabled() { this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) - .withPropertyValues("micrometer.observations.annotations.enabled=false") + .withPropertyValues("management.observations.annotations.enabled=false") .run((context) -> { assertThat(context).doesNotHaveBean(DefaultNewSpanParser.class); assertThat(context).doesNotHaveBean(ImperativeMethodInvocationProcessor.class); @@ -141,6 +140,18 @@ void shouldNotSupplyAspectBeansIfPropertyIsDisabled() { }); } + @Test + void shouldSupplyAspectBeansIfLegacyPropertyIsEnabled() { + new ApplicationContextRunner().withPropertyValues("micrometer.observations.annotations.enabled=true") + .withConfiguration(AutoConfigurations.of(MicrometerTracingAutoConfiguration.class)) + .withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) + .run((context) -> { + assertThat(context).hasSingleBean(DefaultNewSpanParser.class); + assertThat(context).hasSingleBean(ImperativeMethodInvocationProcessor.class); + assertThat(context).hasSingleBean(SpanAspect.class); + }); + } + @Test void shouldNotSupplyBeansIfAspectjIsMissing() { this.contextRunner.withUserConfiguration(TracerConfiguration.class) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 0fe6739f3c44..184f8c80eb92 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -1067,7 +1067,7 @@ Metrics for Jetty's `Connector` instances are bound by using Micrometer's `Jetty [[actuator.metrics.supported.timed-annotation]] ==== @Timed Annotation Support -To enable scanning of `@Timed` annotations, you will need to set the configprop:micrometer.observations.annotations.enabled[] property to `true`. +To enable scanning of `@Timed` annotations, you will need to set the configprop:management.observations.annotations.enabled[] property to `true`. Please refer to the {micrometer-concepts-docs}#_the_timed_annotation[Micrometer documentation]. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc index 54d2e5ba4c96..11b641484d33 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc @@ -92,5 +92,5 @@ The next sections will provide more details about logging, metrics and traces. [[actuator.observability.annotations]] === Micrometer Observation Annotations support -To enable scanning of metrics and tracing annotations like `@Timed`, `@Counted`, `@MeterTag` and `@NewSpan` annotations, you will need to set the configprop:micrometer.observations.annotations.enabled[] property to `true`. +To enable scanning of metrics and tracing annotations like `@Timed`, `@Counted`, `@MeterTag` and `@NewSpan` annotations, you will need to set the configprop:management.observations.annotations.enabled[] property to `true`. This feature is supported Micrometer directly, please refer to the {micrometer-concepts-docs}#_the_timed_annotation[Micrometer] and {micrometer-tracing-docs}/api.html#_aspect_oriented_programming[Micrometer Tracing] reference docs. From 7d73b112397627cccddf91bc081f9a7fe1d4bea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 16 Feb 2024 17:54:16 +0100 Subject: [PATCH 124/182] Fix json path assertion See gh-39605 --- .../RSocketWebSocketNettyRouteProviderTests.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java index a16517fe971d..542e22b1681d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/rsocket/RSocketWebSocketNettyRouteProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -74,7 +74,14 @@ void webEndpointsShouldWork() { .block(Duration.ofSeconds(3)); assertThat(rsocketResponse.getName()).isEqualTo("rsocket"); WebTestClient client = createWebTestClient(serverContext.getWebServer()); - client.get().uri("/protocol").exchange().expectStatus().isOk().expectBody().jsonPath("name", "http"); + client.get() + .uri("/protocol") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .jsonPath("name") + .isEqualTo("http"); }); } From f82a5e10dbd6face6cd0f1b8ca238bb37aa06854 Mon Sep 17 00:00:00 2001 From: Thorsten Schmidt Date: Fri, 16 Feb 2024 11:35:45 +0100 Subject: [PATCH 125/182] Fix local dependent writing of banner into ByteArrayOutputStream See gh-39601 --- .../springframework/boot/SpringApplicationBannerPrinter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java index 4e744703e744..96f340432efd 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java @@ -96,8 +96,8 @@ private Banner getTextBanner(Environment environment) { private String createStringFromBanner(Banner banner, Environment environment, Class mainApplicationClass) throws UnsupportedEncodingException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - banner.printBanner(environment, mainApplicationClass, new PrintStream(baos)); String charset = environment.getProperty("spring.banner.charset", "UTF-8"); + banner.printBanner(environment, mainApplicationClass, new PrintStream(baos, false, charset)); return baos.toString(charset); } From ea2f273cf8c69cfe8b111285e4c6eeadb59e4832 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 19 Feb 2024 11:33:57 +0100 Subject: [PATCH 126/182] Polish "Fix local dependent writing of banner into ByteArrayOutputStream" See gh-39601 --- .../boot/SpringApplicationBannerPrinter.java | 7 +++++-- .../SpringApplicationBannerPrinterTests.java | 18 ++++++++++++++++++ .../src/test/resources/banner-utf8.txt | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/test/resources/banner-utf8.txt diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java index 96f340432efd..b525d819723c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import org.apache.commons.logging.Log; @@ -95,9 +96,11 @@ private Banner getTextBanner(Environment environment) { private String createStringFromBanner(Banner banner, Environment environment, Class mainApplicationClass) throws UnsupportedEncodingException { + String charset = environment.getProperty("spring.banner.charset", StandardCharsets.UTF_8.name()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - String charset = environment.getProperty("spring.banner.charset", "UTF-8"); - banner.printBanner(environment, mainApplicationClass, new PrintStream(baos, false, charset)); + try (PrintStream printStream = new PrintStream(baos, false, charset)) { + banner.printBanner(environment, mainApplicationClass, printStream); + } return baos.toString(charset); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java index 30a112e705db..d4e464f9efa3 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java @@ -16,12 +16,19 @@ package org.springframework.boot; +import org.apache.commons.logging.Log; import org.junit.jupiter.api.Test; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; /** * Tests for {@link SpringApplicationBannerPrinter}. @@ -38,4 +45,15 @@ void shouldRegisterRuntimeHints() { assertThat(RuntimeHintsPredicates.resource().forResource("banner.txt")).accepts(runtimeHints); } + @Test + void shouldUseUtf8() { + ResourceLoader resourceLoader = new GenericApplicationContext(); + Resource resource = resourceLoader.getResource("classpath:/banner-utf8.txt"); + SpringApplicationBannerPrinter printer = new SpringApplicationBannerPrinter(resourceLoader, + new ResourceBanner(resource)); + Log log = mock(Log.class); + printer.print(new MockEnvironment(), SpringApplicationBannerPrinterTests.class, log); + then(log).should().info("\uD83D\uDE0D Spring Boot! \uD83D\uDE0D\n\n"); + } + } diff --git a/spring-boot-project/spring-boot/src/test/resources/banner-utf8.txt b/spring-boot-project/spring-boot/src/test/resources/banner-utf8.txt new file mode 100644 index 000000000000..f3077be2fc5e --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/banner-utf8.txt @@ -0,0 +1 @@ +😍 Spring Boot! 😍 From 6d27c0a9335f8d8fe552d4556e13e99ac96b35e7 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 19 Feb 2024 14:22:18 +0100 Subject: [PATCH 127/182] Fix SpringApplicationBannerPrinterTests on Windows --- .../boot/SpringApplicationBannerPrinterTests.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java index d4e464f9efa3..50250c8c0c00 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2024 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. @@ -18,6 +18,7 @@ import org.apache.commons.logging.Log; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; @@ -53,7 +54,9 @@ void shouldUseUtf8() { new ResourceBanner(resource)); Log log = mock(Log.class); printer.print(new MockEnvironment(), SpringApplicationBannerPrinterTests.class, log); - then(log).should().info("\uD83D\uDE0D Spring Boot! \uD83D\uDE0D\n\n"); + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + then(log).should().info(captor.capture()); + assertThat(captor.getValue()).isEqualToIgnoringNewLines("\uD83D\uDE0D Spring Boot! \uD83D\uDE0D"); } } From 057432c87bca22abd77c18f7d56a8900de5fcd18 Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Sat, 17 Feb 2024 21:18:37 -0800 Subject: [PATCH 128/182] Re-order route registration for GraphQL web endpoints Re-order the route registrations for GraphQL requests so that the most commonly matched path is evaluated first. Closes gh-39613 --- .../graphql/reactive/GraphQlWebFluxAutoConfiguration.java | 2 +- .../graphql/servlet/GraphQlWebMvcAutoConfiguration.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfiguration.java index af590733e2b6..7de9fe72757a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfiguration.java @@ -112,8 +112,8 @@ public RouterFunction graphQlRouterFunction(GraphQlHttpHandler h String path = properties.getPath(); logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path)); RouterFunctions.Builder builder = RouterFunctions.route(); - builder = builder.GET(path, this::onlyAllowPost); builder = builder.POST(path, SUPPORTS_MEDIATYPES, httpHandler::handleRequest); + builder = builder.GET(path, this::onlyAllowPost); if (properties.getGraphiql().isEnabled()) { GraphiQlHandler graphQlHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath()); builder = builder.GET(properties.getGraphiql().getPath(), graphQlHandler::handleRequest); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.java index 4c82ba3b5126..84a907bceeb9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.java @@ -112,9 +112,9 @@ public RouterFunction graphQlRouterFunction(GraphQlHttpHandler h String path = properties.getPath(); logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path)); RouterFunctions.Builder builder = RouterFunctions.route(); - builder = builder.GET(path, this::onlyAllowPost); builder = builder.POST(path, RequestPredicates.contentType(MediaType.APPLICATION_JSON) .and(RequestPredicates.accept(SUPPORTED_MEDIA_TYPES)), httpHandler::handleRequest); + builder = builder.GET(path, this::onlyAllowPost); if (properties.getGraphiql().isEnabled()) { GraphiQlHandler graphiQLHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath()); builder = builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::handleRequest); From 642bd696dd1a8ab327db2415f169538c0672ea0c Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Mon, 19 Feb 2024 21:56:55 -0600 Subject: [PATCH 129/182] Add link to Pulsar env var workaround There is a section in the Pulsar client authentication reference guide that warns users of the lack of relaxed binding for authentication parameter map keys. This lack of relaxed binding prevents users from setting these auth parameters directly via env var as the casing is lost in translation. The commit adds a link in this area of the reference guide to a workaround in the Spring Pulsar framework reference guide. See gh-39630 --- .../spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc index 4a4d435bb5f4..4e0da8a8779e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc @@ -50,6 +50,9 @@ Spring Boot will not attempt any kind of relaxed binding for these entries. For example, if you want to configure the issuer url for the `AuthenticationOAuth2` auth plugin you must use `+spring.pulsar.client.authentication.param.issuerUrl+`. If you use other forms, such as `issuerurl` or `issuer-url`, the setting will not be applied to the plugin. + +This lack of relaxed binding also makes using environment variables for authentication parameters problematic because the case sensitivity is lost during translation. +If you use environment variables for the parameters then you will need to follow {spring-pulsar-docs}reference/pulsar.html#client-authentication-env-vars[these steps] in the Spring for Apache Pulsar reference documentation for it to work properly. ==== From 35e2a12ed8a49ed3f2eb5088969efdcc337861be Mon Sep 17 00:00:00 2001 From: Jakob Wanger Date: Mon, 19 Feb 2024 20:46:13 -0500 Subject: [PATCH 130/182] Clarify that pool size properties are ignored with task executor Signed-off-by: Jakob Wanger See gh-39629 --- .../docs/asciidoc/features/task-execution-and-scheduling.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc index 547be8751408..3f69a73030ef 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc @@ -38,7 +38,7 @@ Shrinking of the pool is more aggressive as threads are reclaimed when they are A scheduler can also be auto-configured if it needs to be associated with scheduled task execution (using `@EnableScheduling` for instance). When virtual threads are enabled (using Java 21+ and configprop:spring.threads.virtual.enabled[] set to `true`) this will be a `SimpleAsyncTaskScheduler` that uses virtual threads. -Otherwise, it will be a `ThreadPoolTaskScheduler` with sensible defaults. +Otherwise, it will be a `ThreadPoolTaskScheduler` with sensible defaults. Note, the `SimpleAsyncTaskScheduler` will ignore any pool size properties. The `ThreadPoolTaskScheduler` uses one thread by default and its settings can be fine-tuned using the `spring.task.scheduling` namespace, as shown in the following example: From cd27dd9fd456db4113effc9e9af7b2bdc7d311ec Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 20 Feb 2024 09:35:59 +0100 Subject: [PATCH 131/182] Polish "Clarify that pool size properties are ignored with task executor" See gh-39629 --- .../asciidoc/features/task-execution-and-scheduling.adoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc index 3f69a73030ef..f238c9b96934 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/task-execution-and-scheduling.adoc @@ -37,9 +37,11 @@ This changes the thread pool to use a bounded queue so that when the queue is fu Shrinking of the pool is more aggressive as threads are reclaimed when they are idle for 10 seconds (rather than 60 seconds by default). A scheduler can also be auto-configured if it needs to be associated with scheduled task execution (using `@EnableScheduling` for instance). -When virtual threads are enabled (using Java 21+ and configprop:spring.threads.virtual.enabled[] set to `true`) this will be a `SimpleAsyncTaskScheduler` that uses virtual threads. -Otherwise, it will be a `ThreadPoolTaskScheduler` with sensible defaults. Note, the `SimpleAsyncTaskScheduler` will ignore any pool size properties. +If virtual threads are enabled (using Java 21+ and configprop:spring.threads.virtual.enabled[] set to `true`) this will be a `SimpleAsyncTaskScheduler` that uses virtual threads. +This `SimpleAsyncTaskScheduler` will ignore any pooling related properties. + +If virtual threads are not enabled, it will be a `ThreadPoolTaskScheduler` with sensible defaults. The `ThreadPoolTaskScheduler` uses one thread by default and its settings can be fine-tuned using the `spring.task.scheduling` namespace, as shown in the following example: [source,yaml,indent=0,subs="verbatim",configprops,configblocks] From 441a012556f18bf52fb7be7020cc89133dacb08d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:27:39 +0000 Subject: [PATCH 132/182] Bump gradle/gradle-build-action from 3.0.0 to 3.1.0 Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/3b1b3b9a2104c2b47fbae53f3938079c00c9bb87...29c0906b64b8fc82467890bfb7a0a7ef34bda89e) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] See gh-39626 --- .github/workflows/build-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 00061b14149f..90673bf5a497 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -23,7 +23,7 @@ jobs: uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 - name: Set up Gradle - uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 + uses: gradle/gradle-build-action@29c0906b64b8fc82467890bfb7a0a7ef34bda89e - name: Build env: From c892544741bd16df49f9373f43083b0bf3f76661 Mon Sep 17 00:00:00 2001 From: Jakob Wanger Date: Sun, 18 Feb 2024 16:33:50 -0500 Subject: [PATCH 133/182] Prevent long parse times for images with illegal char in tag Update the regular expression used to parse Docker images references to prevent catastrophic backtracking when images names are long and the tag contains an illegal character. See gh-39617 --- .../boot/docker/compose/core/Regex.java | 2 +- .../compose/core/ImageReferenceTests.java | 27 ++++++++++++++++++- .../buildpack/platform/docker/type/Regex.java | 4 +-- .../docker/type/ImageReferenceTests.java | 27 ++++++++++++++++++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java index c417ae0d1d47..74e884151794 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java @@ -50,7 +50,7 @@ final class Regex implements CharSequence { private static final Regex PATH_COMPONENT; static { Regex segment = Regex.of("[a-z0-9]+"); - Regex separator = Regex.group("[._]|__|[-]*"); + Regex separator = Regex.group("[._-]{1,2}"); Regex separatedSegment = Regex.group(separator, segment).oneOrMoreTimes(); PATH_COMPONENT = Regex.of(segment, Regex.group(separatedSegment).zeroOrOnce()); } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java index 797b82e09d08..97a479387ebf 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -17,9 +17,12 @@ package org.springframework.boot.docker.compose.core; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.Timeout.ThreadMode; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.fail; /** * Tests for {@link ImageReference}. @@ -165,4 +168,26 @@ void equalsAndHashCode() { assertThat(r1).isEqualTo(r1).isEqualTo(r2).isNotEqualTo(r3); } + @Test + void ofSimpleNameWithSingleCharacterSuffix() { + ImageReference reference = ImageReference.of("ubuntu-a"); + assertThat(reference.getDomain()).isEqualTo("docker.io"); + assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); + assertThat(reference.getTag()).isNull(); + assertThat(reference.getDigest()).isNull(); + assertThat(reference).hasToString("docker.io/library/ubuntu-a"); + } + + @Test + @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) + void ofWhenImageNameIsVeryLongAndHasIllegalCharacter() { + try { + ImageReference + .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234"); + fail("Image Reference contains an illegal character and should have thrown an IllegalArgumentException"); + } + catch (IllegalArgumentException ignored) { + } + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/Regex.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/Regex.java index c843097d100f..648565ee69ba 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/Regex.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/Regex.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -50,7 +50,7 @@ final class Regex implements CharSequence { private static final Regex PATH_COMPONENT; static { Regex segment = Regex.of("[a-z0-9]+"); - Regex separator = Regex.group("[._]|__|[-]*"); + Regex separator = Regex.group("[._-]{1,2}"); Regex separatedSegment = Regex.group(separator, segment).oneOrMoreTimes(); PATH_COMPONENT = Regex.of(segment, Regex.group(separatedSegment).zeroOrOnce()); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java index d33abc7f38b8..b5d2abf29033 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -19,10 +19,13 @@ import java.io.File; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.Timeout.ThreadMode; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.assertj.core.api.Assertions.fail; /** * Tests for {@link ImageReference}. @@ -306,4 +309,26 @@ void inTaglessForm() { assertThat(updated).hasToString("docker.io/library/ubuntu"); } + @Test + void ofSimpleNameWithSingleCharacterSuffix() { + ImageReference reference = ImageReference.of("ubuntu-a"); + assertThat(reference.getDomain()).isEqualTo("docker.io"); + assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); + assertThat(reference.getTag()).isNull(); + assertThat(reference.getDigest()).isNull(); + assertThat(reference).hasToString("docker.io/library/ubuntu-a"); + } + + @Test + @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) + void ofWhenIsVeryLongAndHasIllegalCharacter() { + try { + ImageReference + .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234"); + fail("Contains an illegal character and should have thrown an IllegalArgumentException"); + } + catch (IllegalArgumentException ignored) { + } + } + } From c93acdafbd6de650f5afc7e2d33ff4689f7907c4 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 20 Feb 2024 10:26:46 -0600 Subject: [PATCH 134/182] Polish "Prevent long parse times for images with illegal char in tag" See gh-39617 --- .../compose/core/ImageReferenceTests.java | 43 ++++++++----------- .../docker/type/ImageReferenceTests.java | 43 ++++++++----------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java index 97a479387ebf..e9eb9045819f 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java @@ -22,7 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.fail; /** * Tests for {@link ImageReference}. @@ -42,6 +41,16 @@ void ofSimpleName() { assertThat(reference).hasToString("docker.io/library/ubuntu"); } + @Test + void ofSimpleNameWithSingleCharacterSuffix() { + ImageReference reference = ImageReference.of("ubuntu-a"); + assertThat(reference.getDomain()).isEqualTo("docker.io"); + assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); + assertThat(reference.getTag()).isNull(); + assertThat(reference.getDigest()).isNull(); + assertThat(reference).hasToString("docker.io/library/ubuntu-a"); + } + @Test void ofLibrarySlashName() { ImageReference reference = ImageReference.of("library/ubuntu"); @@ -152,13 +161,21 @@ void ofCustomDomainAndPortWithTag() { } @Test - void ofWhenHasIllegalCharacter() { + void ofWhenHasIllegalCharacterThrowsException() { assertThatIllegalArgumentException() .isThrownBy(() -> ImageReference .of("registry.example.com/example/example-app:1.6.0-dev.2.uncommitted+wip.foo.c75795d")) .withMessageContaining("Unable to parse image reference"); } + @Test + @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) + void ofWhenImageNameIsVeryLongAndHasIllegalCharacterThrowsException() { + assertThatIllegalArgumentException().isThrownBy(() -> ImageReference + .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234")) + .withMessageContaining("Unable to parse image reference"); + } + @Test void equalsAndHashCode() { ImageReference r1 = ImageReference.of("ubuntu:bionic"); @@ -168,26 +185,4 @@ void equalsAndHashCode() { assertThat(r1).isEqualTo(r1).isEqualTo(r2).isNotEqualTo(r3); } - @Test - void ofSimpleNameWithSingleCharacterSuffix() { - ImageReference reference = ImageReference.of("ubuntu-a"); - assertThat(reference.getDomain()).isEqualTo("docker.io"); - assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); - assertThat(reference.getTag()).isNull(); - assertThat(reference.getDigest()).isNull(); - assertThat(reference).hasToString("docker.io/library/ubuntu-a"); - } - - @Test - @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) - void ofWhenImageNameIsVeryLongAndHasIllegalCharacter() { - try { - ImageReference - .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234"); - fail("Image Reference contains an illegal character and should have thrown an IllegalArgumentException"); - } - catch (IllegalArgumentException ignored) { - } - } - } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java index b5d2abf29033..9ec351e503db 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java @@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.assertj.core.api.Assertions.fail; /** * Tests for {@link ImageReference}. @@ -46,6 +45,16 @@ void ofSimpleName() { assertThat(reference).hasToString("docker.io/library/ubuntu"); } + @Test + void ofSimpleNameWithSingleCharacterSuffix() { + ImageReference reference = ImageReference.of("ubuntu-a"); + assertThat(reference.getDomain()).isEqualTo("docker.io"); + assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); + assertThat(reference.getTag()).isNull(); + assertThat(reference.getDigest()).isNull(); + assertThat(reference).hasToString("docker.io/library/ubuntu-a"); + } + @Test void ofLibrarySlashName() { ImageReference reference = ImageReference.of("library/ubuntu"); @@ -176,7 +185,7 @@ void ofImageNameTagAndDigest() { } @Test - void ofWhenHasIllegalCharacter() { + void ofWhenHasIllegalCharacterThrowsException() { assertThatIllegalArgumentException() .isThrownBy(() -> ImageReference .of("registry.example.com/example/example-app:1.6.0-dev.2.uncommitted+wip.foo.c75795d")) @@ -191,6 +200,14 @@ void ofWhenContainsUpperCaseThrowsException() { .withMessageContaining("Unable to parse image reference"); } + @Test + @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) + void ofWhenIsVeryLongAndHasIllegalCharacter() { + assertThatIllegalArgumentException().isThrownBy(() -> ImageReference + .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234")) + .withMessageContaining("Unable to parse image reference"); + } + @Test void forJarFile() { assertForJarFile("spring-boot.2.0.0.BUILD-SNAPSHOT.jar", "library/spring-boot", "2.0.0.BUILD-SNAPSHOT"); @@ -309,26 +326,4 @@ void inTaglessForm() { assertThat(updated).hasToString("docker.io/library/ubuntu"); } - @Test - void ofSimpleNameWithSingleCharacterSuffix() { - ImageReference reference = ImageReference.of("ubuntu-a"); - assertThat(reference.getDomain()).isEqualTo("docker.io"); - assertThat(reference.getName()).isEqualTo("library/ubuntu-a"); - assertThat(reference.getTag()).isNull(); - assertThat(reference.getDigest()).isNull(); - assertThat(reference).hasToString("docker.io/library/ubuntu-a"); - } - - @Test - @Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD) - void ofWhenIsVeryLongAndHasIllegalCharacter() { - try { - ImageReference - .of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234"); - fail("Contains an illegal character and should have thrown an IllegalArgumentException"); - } - catch (IllegalArgumentException ignored) { - } - } - } From 4c069f0079676c62134f8401886bc5bed17e8ebf Mon Sep 17 00:00:00 2001 From: Jakob Wanger Date: Mon, 19 Feb 2024 17:24:23 -0500 Subject: [PATCH 135/182] Add note regarding mixing of bundle-based and direct SSL configuration Signed-off-by: Jakob Wanger See gh-39616 --- .../spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc index e1b98ecd29d6..c6a5e470929a 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc @@ -172,8 +172,7 @@ The following example shows setting SSL properties using a Java KeyStore file: Using configuration such as the preceding example means the application no longer supports a plain HTTP connector at port 8080. Spring Boot does not support the configuration of both an HTTP connector and an HTTPS connector through `application.properties`. If you want to have both, you need to configure one of them programmatically. -We recommend using `application.properties` to configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically. - +We recommend using `application.properties` to configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically. Also note that Spring Boot does not support the mixing of different configuration methods of SSL for embedded web servers, as such the use of the `ssl.bundle` property can't be combined with the discrete JKS or PEM property options under `server.ssl`. [[howto.webserver.configure-ssl.pem-files]] From eb4d6e7c15099a8ecd1b8ad4aed9a551e2189149 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 20 Feb 2024 11:46:44 -0600 Subject: [PATCH 136/182] Polish "Add note regarding mixing of bundle-based and direct SSL configuration" See gh-39616 --- .../spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc index c6a5e470929a..49a81caa449f 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/webserver.adoc @@ -172,7 +172,8 @@ The following example shows setting SSL properties using a Java KeyStore file: Using configuration such as the preceding example means the application no longer supports a plain HTTP connector at port 8080. Spring Boot does not support the configuration of both an HTTP connector and an HTTPS connector through `application.properties`. If you want to have both, you need to configure one of them programmatically. -We recommend using `application.properties` to configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically. Also note that Spring Boot does not support the mixing of different configuration methods of SSL for embedded web servers, as such the use of the `ssl.bundle` property can't be combined with the discrete JKS or PEM property options under `server.ssl`. +We recommend using `application.properties` to configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically. + [[howto.webserver.configure-ssl.pem-files]] @@ -210,6 +211,8 @@ Alternatively, the SSL trust material can be configured in an < Date: Wed, 21 Feb 2024 10:20:07 +0100 Subject: [PATCH 137/182] Migrate to gradle/actions/setup-gradle Closes gh-39645 --- .github/workflows/build-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 90673bf5a497..e5956ae140b5 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -23,7 +23,7 @@ jobs: uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 - name: Set up Gradle - uses: gradle/gradle-build-action@29c0906b64b8fc82467890bfb7a0a7ef34bda89e + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 - name: Build env: From b4304af23fa6eaef37fb81fd3434f6dc8571f0d1 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:05 +0000 Subject: [PATCH 138/182] Upgrade to Byte Buddy 1.14.12 Closes gh-39659 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e0b1365125de..b9dbfa58a753 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -123,7 +123,7 @@ bom { ] } } - library("Byte Buddy", "1.14.11") { + library("Byte Buddy", "1.14.12") { group("net.bytebuddy") { modules = [ "byte-buddy", From 319331175aa8e00eac664f9a4b1626dd5ce2c782 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:10 +0000 Subject: [PATCH 139/182] Upgrade to Jackson Bom 2.15.4 Closes gh-39660 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7bf2056e2de1..c8c2fa47f57c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 assertjVersion=3.24.2 commonsCodecVersion=1.15 hamcrestVersion=2.2 -jacksonVersion=2.15.3 +jacksonVersion=2.15.4 junitJupiterVersion=5.9.3 kotlinVersion=1.8.22 mavenVersion=3.9.4 From 85a8364d73fd668e54bffb6edd7254e9fbe12738 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:15 +0000 Subject: [PATCH 140/182] Upgrade to jOOQ 3.18.11 Closes gh-39661 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index b9dbfa58a753..be0840ae6534 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -680,7 +680,7 @@ bom { ] } } - library("jOOQ", "3.18.10") { + library("jOOQ", "3.18.11") { group("org.jooq") { modules = [ "jooq", From f45dfff08217f496ddc8818400319f4f8838d632 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:20 +0000 Subject: [PATCH 141/182] Upgrade to Postgresql 42.6.1 Closes gh-39662 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index be0840ae6534..60f5e9868bd8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1103,7 +1103,7 @@ bom { ] } } - library("Postgresql", "42.6.0") { + library("Postgresql", "42.6.1") { group("org.postgresql") { modules = [ "postgresql" From 152d9832789b1a144f7d275583e158eceb3df0d4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:20 +0000 Subject: [PATCH 142/182] Upgrade to Reactor Bom 2022.0.16 Closes gh-39456 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 60f5e9868bd8..0c96a61e97dd 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1217,7 +1217,7 @@ bom { ] } } - library("Reactor Bom", "2022.0.16-SNAPSHOT") { + library("Reactor Bom", "2022.0.16") { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { From 79b650543047f2bb3cb88a7bf537425416a59bf4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:21 +0000 Subject: [PATCH 143/182] Upgrade to Spring AMQP 3.0.11 Closes gh-39457 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0c96a61e97dd..e721035a007f 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1382,7 +1382,7 @@ bom { ] } } - library("Spring AMQP", "3.0.11-SNAPSHOT") { + library("Spring AMQP", "3.0.11") { considerSnapshots() group("org.springframework.amqp") { imports = [ From 06f6bba0e30f997f6b906685004f63a8273b6e20 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:22 +0000 Subject: [PATCH 144/182] Upgrade to Spring Authorization Server 1.1.5 Closes gh-39458 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e721035a007f..0632cea00d54 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1390,7 +1390,7 @@ bom { ] } } - library("Spring Authorization Server", "1.1.5-SNAPSHOT") { + library("Spring Authorization Server", "1.1.5") { considerSnapshots() group("org.springframework.security") { modules = [ From 0e06315956b3826a0d4882c0714c1cc06b761da5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:22 +0000 Subject: [PATCH 145/182] Upgrade to Spring Batch 5.0.5 Closes gh-39459 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0632cea00d54..3e402c88a066 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1398,7 +1398,7 @@ bom { ] } } - library("Spring Batch", "5.0.5-SNAPSHOT") { + library("Spring Batch", "5.0.5") { considerSnapshots() group("org.springframework.batch") { imports = [ From 57d46423f7eb81d4ff61e5c2dc2afef23ec97b41 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:23 +0000 Subject: [PATCH 146/182] Upgrade to Spring Data Bom 2023.0.9 Closes gh-39460 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3e402c88a066..8b9ac76e2fb4 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1406,7 +1406,7 @@ bom { ] } } - library("Spring Data Bom", "2023.0.9-SNAPSHOT") { + library("Spring Data Bom", "2023.0.9") { considerSnapshots() calendarName = "Spring Data Release" group("org.springframework.data") { From c6c9a7c9f913a472c2b9f2b82c84ba55a40d120a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:23 +0000 Subject: [PATCH 147/182] Upgrade to Spring Framework 6.0.17 Closes gh-39461 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c8c2fa47f57c..acf983594f54 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ junitJupiterVersion=5.9.3 kotlinVersion=1.8.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 -springFrameworkVersion=6.0.17-SNAPSHOT +springFrameworkVersion=6.0.17 tomcatVersion=10.1.18 kotlin.stdlib.default.dependency=false From d14fa83690947c802ccafd411f003fae750cb30c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:24 +0000 Subject: [PATCH 148/182] Upgrade to Spring GraphQL 1.2.5 Closes gh-39462 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 8b9ac76e2fb4..32d08e83f0d8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1424,7 +1424,7 @@ bom { ] } } - library("Spring GraphQL", "1.2.5-SNAPSHOT") { + library("Spring GraphQL", "1.2.5") { considerSnapshots() group("org.springframework.graphql") { modules = [ From 6a67eea361985aa807acd5cc2031f03541305f2d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:25 +0000 Subject: [PATCH 149/182] Upgrade to Spring Integration 6.1.6 Closes gh-39463 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 32d08e83f0d8..97e4e1cb08a9 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1441,7 +1441,7 @@ bom { ] } } - library("Spring Integration", "6.1.6-SNAPSHOT") { + library("Spring Integration", "6.1.6") { considerSnapshots() group("org.springframework.integration") { imports = [ From 103618269248a22038c30fa0df2edd5301a39018 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:25 +0000 Subject: [PATCH 150/182] Upgrade to Spring Kafka 3.0.14 Closes gh-39464 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 97e4e1cb08a9..db424873b9dc 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1449,7 +1449,7 @@ bom { ] } } - library("Spring Kafka", "3.0.14-SNAPSHOT") { + library("Spring Kafka", "3.0.14") { considerSnapshots() group("org.springframework.kafka") { modules = [ From f0da887f172251fd5001a965586cd21c9a2e0220 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:26 +0000 Subject: [PATCH 151/182] Upgrade to Spring LDAP 3.1.4 Closes gh-39465 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index db424873b9dc..e99f3fa5c909 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1458,7 +1458,7 @@ bom { ] } } - library("Spring LDAP", "3.1.4-SNAPSHOT") { + library("Spring LDAP", "3.1.4") { considerSnapshots() group("org.springframework.ldap") { modules = [ From 1c5858e59f88bcd9660754b80b4f8e1153f2c8c3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:26 +0000 Subject: [PATCH 152/182] Upgrade to Spring Security 6.1.7 Closes gh-39466 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index e99f3fa5c909..a884a347463c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1485,7 +1485,7 @@ bom { ] } } - library("Spring Security", "6.1.7-SNAPSHOT") { + library("Spring Security", "6.1.7") { considerSnapshots() group("org.springframework.security") { imports = [ From 2581c5c87a28cbfc8d4381f65454ced40a0198b2 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:31 +0000 Subject: [PATCH 153/182] Upgrade to Tomcat 10.1.19 Closes gh-39663 --- gradle.properties | 2 +- .../web/embedded/tomcat/GracefulShutdown.java | 50 ++++++++++++------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/gradle.properties b/gradle.properties index acf983594f54..0183c8f5fb17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,6 @@ kotlinVersion=1.8.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 springFrameworkVersion=6.0.17 -tomcatVersion=10.1.18 +tomcatVersion=10.1.19 kotlin.stdlib.default.dependency=false diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java index c921cf5c94aa..b94f92c6d3da 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2024 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. @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; import org.apache.catalina.Container; import org.apache.catalina.Service; @@ -51,32 +52,45 @@ final class GracefulShutdown { void shutDownGracefully(GracefulShutdownCallback callback) { logger.info("Commencing graceful shutdown. Waiting for active requests to complete"); - new Thread(() -> doShutdown(callback), "tomcat-shutdown").start(); + CountDownLatch shutdownUnderway = new CountDownLatch(1); + new Thread(() -> doShutdown(callback, shutdownUnderway), "tomcat-shutdown").start(); + try { + shutdownUnderway.await(); + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } } - private void doShutdown(GracefulShutdownCallback callback) { - List connectors = getConnectors(); - connectors.forEach(this::close); + private void doShutdown(GracefulShutdownCallback callback, CountDownLatch shutdownUnderway) { try { - for (Container host : this.tomcat.getEngine().findChildren()) { - for (Container context : host.findChildren()) { - while (isActive(context)) { - if (this.aborted) { - logger.info("Graceful shutdown aborted with one or more requests still active"); - callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); - return; + List connectors = getConnectors(); + connectors.forEach(this::close); + shutdownUnderway.countDown(); + try { + for (Container host : this.tomcat.getEngine().findChildren()) { + for (Container context : host.findChildren()) { + while (isActive(context)) { + if (this.aborted) { + logger.info("Graceful shutdown aborted with one or more requests still active"); + callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); + return; + } + Thread.sleep(50); } - Thread.sleep(50); } } - } + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + logger.info("Graceful shutdown complete"); + callback.shutdownComplete(GracefulShutdownResult.IDLE); } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + finally { + shutdownUnderway.countDown(); } - logger.info("Graceful shutdown complete"); - callback.shutdownComplete(GracefulShutdownResult.IDLE); } private List getConnectors() { From 3e46fff15cf30730557a5ff266a1118702a1240a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 20:09:36 +0000 Subject: [PATCH 154/182] Upgrade to Undertow 2.3.12.Final Closes gh-39664 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a884a347463c..702c72b3dd91 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1580,7 +1580,7 @@ bom { ] } } - library("Undertow", "2.3.11.Final") { + library("Undertow", "2.3.12.Final") { group("io.undertow") { modules = [ "undertow-core", From 9c43e8545c06d8e31cebd1656ae52aaf323430da Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:04:58 +0000 Subject: [PATCH 155/182] Upgrade to Byte Buddy 1.14.12 Closes gh-39665 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 67314a4265cb..60af3d83a936 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -123,7 +123,7 @@ bom { ] } } - library("Byte Buddy", "1.14.11") { + library("Byte Buddy", "1.14.12") { group("net.bytebuddy") { modules = [ "byte-buddy", From cceb7fd609c469bba2012067e5cf95428c7171e5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:03 +0000 Subject: [PATCH 156/182] Upgrade to Jackson Bom 2.15.4 Closes gh-39666 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7121b3e74eec..811098d49ecf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ assertjVersion=3.24.2 commonsCodecVersion=1.16.1 commonsCompressVersion=1.21 hamcrestVersion=2.2 -jacksonVersion=2.15.3 +jacksonVersion=2.15.4 junitJupiterVersion=5.10.2 kotlinVersion=1.9.22 mavenVersion=3.9.4 From b163b70b2896079811b03d154996e5308a50cb21 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:09 +0000 Subject: [PATCH 157/182] Upgrade to jOOQ 3.18.11 Closes gh-39667 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 60af3d83a936..a1ac6fcc59a8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -697,7 +697,7 @@ bom { ] } } - library("jOOQ", "3.18.10") { + library("jOOQ", "3.18.11") { group("org.jooq") { modules = [ "jooq", From edc80ec39a9f8cf47090d2c6f945c5fa26b717e8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:14 +0000 Subject: [PATCH 158/182] Upgrade to Kotlin Serialization 1.6.3 Closes gh-39668 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a1ac6fcc59a8..3c8ac242b983 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -814,7 +814,7 @@ bom { ] } } - library("Kotlin Serialization", "1.6.2") { + library("Kotlin Serialization", "1.6.3") { group("org.jetbrains.kotlinx") { imports = [ "kotlinx-serialization-bom" From 4924af999943dc74188ccacc6582cad2b06f32a7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:19 +0000 Subject: [PATCH 159/182] Upgrade to MariaDB 3.3.3 Closes gh-39669 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 3c8ac242b983..c74f0a23628f 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -862,7 +862,7 @@ bom { ] } } - library("MariaDB", "3.3.2") { + library("MariaDB", "3.3.3") { group("org.mariadb.jdbc") { modules = [ "mariadb-java-client" From 2fa921c010a4e53dcc7f3714fb54c1a7a76f7f69 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:24 +0000 Subject: [PATCH 160/182] Upgrade to Maven Shade Plugin 3.5.2 Closes gh-39670 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c74f0a23628f..a10880860ea0 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -967,7 +967,7 @@ bom { ] } } - library("Maven Shade Plugin", "3.5.1") { + library("Maven Shade Plugin", "3.5.2") { group("org.apache.maven.plugins") { plugins = [ "maven-shade-plugin" From 9411da2a2452739739eeeb8013807ebccd5e8a4e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:29 +0000 Subject: [PATCH 161/182] Upgrade to Postgresql 42.6.1 Closes gh-39671 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index a10880860ea0..146b27c4b3d3 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1123,7 +1123,7 @@ bom { ] } } - library("Postgresql", "42.6.0") { + library("Postgresql", "42.6.1") { group("org.postgresql") { modules = [ "postgresql" From fcc1e1e806597f077182ae0359791f6d1bb76339 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:33 +0000 Subject: [PATCH 162/182] Upgrade to Pulsar Reactive 0.5.3 Closes gh-39672 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 146b27c4b3d3..ac938dd458ac 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1216,7 +1216,7 @@ bom { ] } } - library("Pulsar Reactive", "0.5.2") { + library("Pulsar Reactive", "0.5.3") { group("org.apache.pulsar") { modules = [ "pulsar-client-reactive-adapter", From bc6282520192f51e566445a4ecd66c44f538b1fa Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:34 +0000 Subject: [PATCH 163/182] Upgrade to Reactor Bom 2023.0.3 Closes gh-39476 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index ac938dd458ac..62afcbbf1689 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1327,7 +1327,7 @@ bom { ] } } - library("Reactor Bom", "2023.0.3-SNAPSHOT") { + library("Reactor Bom", "2023.0.3") { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { From 32da1bf3a15ed26ecfcce860c7e04dd6ca390e58 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:35 +0000 Subject: [PATCH 164/182] Upgrade to Spring AMQP 3.1.2 Closes gh-39477 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 62afcbbf1689..c30c4e7329ea 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1495,7 +1495,7 @@ bom { ] } } - library("Spring AMQP", "3.1.2-SNAPSHOT") { + library("Spring AMQP", "3.1.2") { considerSnapshots() group("org.springframework.amqp") { imports = [ From c20b274cefdfa078f13ba39a7f970a705b949291 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:36 +0000 Subject: [PATCH 165/182] Upgrade to Spring Authorization Server 1.2.2 Closes gh-39478 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c30c4e7329ea..f30d3f2d719d 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1503,7 +1503,7 @@ bom { ] } } - library("Spring Authorization Server", "1.2.2-SNAPSHOT") { + library("Spring Authorization Server", "1.2.2") { considerSnapshots() group("org.springframework.security") { modules = [ From ae464bfb2dd17b31306e315b2ca602dc924f44c8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:37 +0000 Subject: [PATCH 166/182] Upgrade to Spring Batch 5.1.1 Closes gh-39479 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f30d3f2d719d..f9d048123503 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1511,7 +1511,7 @@ bom { ] } } - library("Spring Batch", "5.1.1-SNAPSHOT") { + library("Spring Batch", "5.1.1") { considerSnapshots() group("org.springframework.batch") { imports = [ From adefc21024a64eae115d2eef0e3daa522573ef69 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:37 +0000 Subject: [PATCH 167/182] Upgrade to Spring Data Bom 2023.1.3 Closes gh-39480 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f9d048123503..5e44d757729d 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1519,7 +1519,7 @@ bom { ] } } - library("Spring Data Bom", "2023.1.3-SNAPSHOT") { + library("Spring Data Bom", "2023.1.3") { considerSnapshots() calendarName = "Spring Data Release" group("org.springframework.data") { From 3b9b4f2b7956e131a2078caf243da249eb7b20ef Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:38 +0000 Subject: [PATCH 168/182] Upgrade to Spring Framework 6.1.4 Closes gh-39481 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 811098d49ecf..20e8df7090b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ junitJupiterVersion=5.10.2 kotlinVersion=1.9.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 -springFrameworkVersion=6.1.4-SNAPSHOT +springFrameworkVersion=6.1.4 tomcatVersion=10.1.18 kotlin.stdlib.default.dependency=false From e67ee7a081c5fc96c5531ecac554fac58817471d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:39 +0000 Subject: [PATCH 169/182] Upgrade to Spring GraphQL 1.2.5 Closes gh-39482 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 5e44d757729d..ad6d5aa91102 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1537,7 +1537,7 @@ bom { ] } } - library("Spring GraphQL", "1.2.5-SNAPSHOT") { + library("Spring GraphQL", "1.2.5") { considerSnapshots() group("org.springframework.graphql") { modules = [ From 398fb157581b0cfc3cad0ae1a454bbc23797e597 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:39 +0000 Subject: [PATCH 170/182] Upgrade to Spring Integration 6.2.2 Closes gh-39483 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index ad6d5aa91102..21c68ad1c326 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1554,7 +1554,7 @@ bom { ] } } - library("Spring Integration", "6.2.2-SNAPSHOT") { + library("Spring Integration", "6.2.2") { considerSnapshots() group("org.springframework.integration") { imports = [ From 506438e7728e295cfa7cc40e77e581f0cd90c028 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:40 +0000 Subject: [PATCH 171/182] Upgrade to Spring Kafka 3.1.2 Closes gh-39484 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 21c68ad1c326..6a1b770b4ce3 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1562,7 +1562,7 @@ bom { ] } } - library("Spring Kafka", "3.1.2-SNAPSHOT") { + library("Spring Kafka", "3.1.2") { considerSnapshots() group("org.springframework.kafka") { modules = [ From 6158fa08c9a93c422e068fe2fe40c6e2da2f5266 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:41 +0000 Subject: [PATCH 172/182] Upgrade to Spring LDAP 3.2.2 Closes gh-39485 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6a1b770b4ce3..0c32d2d67fdc 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1571,7 +1571,7 @@ bom { ] } } - library("Spring LDAP", "3.2.2-SNAPSHOT") { + library("Spring LDAP", "3.2.2") { considerSnapshots() group("org.springframework.ldap") { modules = [ From 34a45d26081bc3fecb7fc0027550edf0fbb3a745 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:42 +0000 Subject: [PATCH 173/182] Upgrade to Spring Pulsar 1.0.3 Closes gh-39486 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 0c32d2d67fdc..c7973cd0f8a2 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1582,7 +1582,7 @@ bom { ] } } - library("Spring Pulsar", "1.0.3-SNAPSHOT") { + library("Spring Pulsar", "1.0.3") { considerSnapshots() group("org.springframework.pulsar") { imports = [ From d86fa721b577a1c5136994c22506b6d84fd52ce4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:43 +0000 Subject: [PATCH 174/182] Upgrade to Spring Security 6.2.2 Closes gh-39487 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index c7973cd0f8a2..99f7bd4da22b 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1606,7 +1606,7 @@ bom { ] } } - library("Spring Security", "6.2.2-SNAPSHOT") { + library("Spring Security", "6.2.2") { considerSnapshots() group("org.springframework.security") { imports = [ From 71e3a92f3ced4645d03c5a5c2090528522c6ff6e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:47 +0000 Subject: [PATCH 175/182] Upgrade to Tomcat 10.1.19 Closes gh-39673 --- gradle.properties | 2 +- .../web/embedded/tomcat/GracefulShutdown.java | 51 ++++++++++++------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/gradle.properties b/gradle.properties index 20e8df7090b7..c6724149b9d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,6 @@ kotlinVersion=1.9.22 mavenVersion=3.9.4 nativeBuildToolsVersion=0.9.28 springFrameworkVersion=6.1.4 -tomcatVersion=10.1.18 +tomcatVersion=10.1.19 kotlin.stdlib.default.dependency=false diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java index 3215a0de8609..2accad1852a9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/GracefulShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; import org.apache.catalina.Container; import org.apache.catalina.Service; @@ -51,32 +52,44 @@ final class GracefulShutdown { void shutDownGracefully(GracefulShutdownCallback callback) { logger.info("Commencing graceful shutdown. Waiting for active requests to complete"); - new Thread(() -> doShutdown(callback), "tomcat-shutdown").start(); + CountDownLatch shutdownUnderway = new CountDownLatch(1); + new Thread(() -> doShutdown(callback, shutdownUnderway), "tomcat-shutdown").start(); + try { + shutdownUnderway.await(); + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } } - private void doShutdown(GracefulShutdownCallback callback) { - List connectors = getConnectors(); - connectors.forEach(this::close); + private void doShutdown(GracefulShutdownCallback callback, CountDownLatch shutdownUnderway) { try { - for (Container host : this.tomcat.getEngine().findChildren()) { - for (Container context : host.findChildren()) { - while (!this.aborted && isActive(context)) { - Thread.sleep(50); - } - if (this.aborted) { - logger.info("Graceful shutdown aborted with one or more requests still active"); - callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); - return; + List connectors = getConnectors(); + connectors.forEach(this::close); + shutdownUnderway.countDown(); + try { + for (Container host : this.tomcat.getEngine().findChildren()) { + for (Container context : host.findChildren()) { + while (!this.aborted && isActive(context)) { + Thread.sleep(50); + } + if (this.aborted) { + logger.info("Graceful shutdown aborted with one or more requests still active"); + callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE); + return; + } } } } - + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + logger.info("Graceful shutdown complete"); + callback.shutdownComplete(GracefulShutdownResult.IDLE); } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + finally { + shutdownUnderway.countDown(); } - logger.info("Graceful shutdown complete"); - callback.shutdownComplete(GracefulShutdownResult.IDLE); } private List getConnectors() { From b199e49e404aef8810d6dc78580844b76114166a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Feb 2024 21:05:53 +0000 Subject: [PATCH 176/182] Upgrade to Undertow 2.3.12.Final Closes gh-39674 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 99f7bd4da22b..e5f445ef646c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1701,7 +1701,7 @@ bom { ] } } - library("Undertow", "2.3.11.Final") { + library("Undertow", "2.3.12.Final") { group("io.undertow") { modules = [ "undertow-core", From 2c4909a89af5e4db49bbb17d7db253e7e3a03a5a Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 21 Feb 2024 13:58:53 -0800 Subject: [PATCH 177/182] Update copyright year of changed files --- .../web/documentation/SessionsEndpointDocumentationTests.java | 2 +- .../org/springframework/boot/docker/compose/core/Regex.java | 2 +- .../springframework/boot/gradle/plugin/SpringBootPlugin.java | 2 +- .../boot/gradle/plugin/SpringBootPluginIntegrationTests.java | 2 +- .../java/org/springframework/boot/maven/RunArgumentsTests.java | 2 +- .../springframework/boot/SpringApplicationBannerPrinter.java | 2 +- .../springframework/boot/image/paketo/PaketoBuilderTests.java | 2 +- .../java/smoketest/actuator/SampleActuatorApplicationTests.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java index c33020828cfd..c92c522005bf 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/SessionsEndpointDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java index 74e884151794..b6ae27942d44 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java index 0ff7ca3ac803..af3a1f1bf91a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java index 59c7cd1b0580..8128321c3872 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/SpringBootPluginIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java index e3b4d1d0c1e2..388d5bfba423 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RunArgumentsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java index b525d819723c..e104dedc2fc0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java index 478be5eb1bc8..51e0ad447073 100644 --- a/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java +++ b/spring-boot-system-tests/spring-boot-image-tests/src/systemTest/java/org/springframework/boot/image/paketo/PaketoBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java index 360e0719a5a1..ca12587bf87b 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/SampleActuatorApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. From 39304147a7631c88268622f8552527e17a285b56 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Wed, 21 Feb 2024 17:58:39 -0600 Subject: [PATCH 178/182] Upgrade CI images to ubuntu:jammy-20240212 Closes gh-39657 --- ci/images/ci-image-jdk21/Dockerfile | 2 +- ci/images/ci-image/Dockerfile | 2 +- .../intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile | 4 ++-- .../src/intTest/resources/conf/oracle-jdk-17/Dockerfile | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/images/ci-image-jdk21/Dockerfile b/ci/images/ci-image-jdk21/Dockerfile index 777a94f0a731..b4c9aa527a66 100644 --- a/ci/images/ci-image-jdk21/Dockerfile +++ b/ci/images/ci-image-jdk21/Dockerfile @@ -1,5 +1,5 @@ ARG DOCKER_PROXY_CACHE= -FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240125 +FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240212 ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh diff --git a/ci/images/ci-image/Dockerfile b/ci/images/ci-image/Dockerfile index 581c18b9de00..450bb5ee4668 100644 --- a/ci/images/ci-image/Dockerfile +++ b/ci/images/ci-image/Dockerfile @@ -1,5 +1,5 @@ ARG DOCKER_PROXY_CACHE= -FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240125 +FROM ${DOCKER_PROXY_CACHE}ubuntu:jammy-20240212 ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile index 3ed174cd2605..39c971efaf85 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/intTest/resources/conf/Ubuntu/jammy-20240111/Dockerfile @@ -1,10 +1,10 @@ -FROM ubuntu:jammy-20240125 as prepare +FROM ubuntu:jammy-20240212 as prepare COPY downloads/* /opt/download/ RUN mkdir -p /opt/jdk && \ cd /opt/jdk && \ tar xzf /opt/download/* --strip-components=1 -FROM ubuntu:jammy-20240125 +FROM ubuntu:jammy-20240212 RUN apt-get update && apt-get install -y software-properties-common curl COPY --from=prepare /opt/jdk /opt/jdk ENV JAVA_HOME /opt/jdk diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile index 2141eaa09fd6..f16f5d10d08d 100644 --- a/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile +++ b/spring-boot-tests/spring-boot-integration-tests/spring-boot-loader-tests/src/intTest/resources/conf/oracle-jdk-17/Dockerfile @@ -1,10 +1,10 @@ -FROM ubuntu:jammy-20240125 as prepare +FROM ubuntu:jammy-20240212 as prepare COPY downloads/* /opt/download/ RUN mkdir -p /opt/jdk && \ cd /opt/jdk && \ tar xzf /opt/download/* --strip-components=1 -FROM ubuntu:jammy-20240125 +FROM ubuntu:jammy-20240212 COPY --from=prepare /opt/jdk /opt/jdk ENV JAVA_HOME /opt/jdk ENV PATH $JAVA_HOME/bin:$PATH From 06569e76f6155562bc0220fc97a8ac641e57a56d Mon Sep 17 00:00:00 2001 From: "_ext Slovak, Jiri" Date: Wed, 21 Feb 2024 22:00:23 +0100 Subject: [PATCH 179/182] Decode URL content before passing it to NestedLocation.parse URL can contains empty spaced encoded as %20, so it should be decoded before passing it to NestedLocation. NestedLocation expects file system path which should not contain URL encoded values. See gh-39675 --- .../boot/loader/net/protocol/nested/NestedUrlConnection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java index 0409fe6e3d99..3dd03491f441 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java @@ -38,6 +38,7 @@ import java.util.Map; import java.util.Map.Entry; +import org.springframework.boot.loader.net.util.UrlDecoder; import org.springframework.boot.loader.ref.Cleaner; /** @@ -76,7 +77,7 @@ class NestedUrlConnection extends URLConnection { private NestedLocation parseNestedLocation(URL url) throws MalformedURLException { try { - return NestedLocation.parse(url.getPath()); + return NestedLocation.parse(UrlDecoder.decode(url.getPath())); } catch (IllegalArgumentException ex) { throw new MalformedURLException(ex.getMessage()); From a457638e6c764b020eeb9e7a1ecde157f0bc9462 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 21 Feb 2024 17:30:12 -0800 Subject: [PATCH 180/182] Polish 'Decode URL content before passing it to NestedLocation.parse' See gh-39675' Closes gh-39675' --- .../protocol/nested/NestedUrlConnection.java | 2 +- .../nested/NestedUrlConnectionTests.java | 31 ++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java index 3dd03491f441..7daac7ee950f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnectionTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnectionTests.java index b194610486e2..606d00c53edc 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnectionTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/protocol/nested/NestedUrlConnectionTests.java @@ -121,13 +121,7 @@ void getPermissionReturnsFilePermission() throws Exception { @Test void getInputStreamReturnsContentOfNestedJar() throws Exception { NestedUrlConnection connection = new NestedUrlConnection(this.url); - try (InputStream actual = connection.getInputStream()) { - try (ZipContent zipContent = ZipContent.open(this.jarFile.toPath())) { - try (InputStream expected = zipContent.getEntry("nested.jar").openContent().asInputStream()) { - assertThat(actual).hasSameContentAs(expected); - } - } - } + assertHasSameContentAsNestedJar(connection); } @Test @@ -163,6 +157,29 @@ void getLastModifiedHeaderReturnsFileModifiedTime() throws IOException { } } + @Test + void createDecodesUrlPath() throws Exception { + File withSpace = new File(this.temp, "te st"); + withSpace.mkdirs(); + this.jarFile = new File(withSpace, "test.jar"); + TestJar.create(this.jarFile); + this.url = new URL("nested:" + this.jarFile.toURI().getRawPath() + "/!nested.jar"); + assertThat(this.url.toString()).contains("%20"); + NestedUrlConnection connection = new NestedUrlConnection(this.url); + assertHasSameContentAsNestedJar(connection); + assertThat(connection.getLastModified()).isEqualTo(this.jarFile.lastModified()); + } + + private void assertHasSameContentAsNestedJar(NestedUrlConnection connection) throws IOException { + try (InputStream actual = connection.getInputStream()) { + try (ZipContent zipContent = ZipContent.open(this.jarFile.toPath())) { + try (InputStream expected = zipContent.getEntry("nested.jar").openContent().asInputStream()) { + assertThat(actual).hasSameContentAs(expected); + } + } + } + } + private long withoutNanos(long epochMilli) { return Instant.ofEpochMilli(epochMilli).with(ChronoField.NANO_OF_SECOND, 0).toEpochMilli(); } From 8dff2496dc956b987668fe7c89208073ecbcc103 Mon Sep 17 00:00:00 2001 From: Spring Builds Date: Thu, 22 Feb 2024 11:35:44 +0000 Subject: [PATCH 181/182] Next development version (v3.1.10-SNAPSHOT) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0183c8f5fb17..44a840339861 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=3.1.9-SNAPSHOT +version=3.1.10-SNAPSHOT org.gradle.caching=true org.gradle.parallel=true From c24afefb4d46e78b774c67eda1fd4f822f12bbee Mon Sep 17 00:00:00 2001 From: Spring Builds Date: Thu, 22 Feb 2024 18:24:18 +0000 Subject: [PATCH 182/182] Release v3.2.3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c6724149b9d8..65a5c1668c2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=3.2.3-SNAPSHOT +version=3.2.3 org.gradle.caching=true org.gradle.parallel=true