diff --git a/gradle.properties b/gradle.properties index 325508af105d..b8110286ab21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=3.4.5-SNAPSHOT +version=3.4.6-SNAPSHOT latestVersion=false spring.build-type=oss diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java index ac538c616c87..0930901cad66 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java @@ -186,6 +186,7 @@ protected final List getDelegateMatchers(Set p } private PathPatternParserServerWebExchangeMatcher getDelegateMatcher(String path) { + Assert.notNull(path, "'path' must not be null"); return new PathPatternParserServerWebExchangeMatcher(path + "/**"); } @@ -310,11 +311,18 @@ protected ServerWebExchangeMatcher createDelegate(PathMappedEndpoints endpoints) if (this.includeLinks && StringUtils.hasText(endpoints.getBasePath())) { delegateMatchers.add(new LinksServerWebExchangeMatcher()); } + if (delegateMatchers.isEmpty()) { + return EMPTY_MATCHER; + } return new OrServerWebExchangeMatcher(delegateMatchers); } private Stream streamPaths(List source, PathMappedEndpoints endpoints) { - return source.stream().filter(Objects::nonNull).map(this::getEndpointId).map(endpoints::getPath); + return source.stream() + .filter(Objects::nonNull) + .map(this::getEndpointId) + .map(endpoints::getPath) + .filter(Objects::nonNull); } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java index 6fcc1630625f..5054f4758628 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java @@ -329,11 +329,18 @@ protected RequestMatcher createDelegate(WebApplicationContext context, if (this.includeLinks && StringUtils.hasText(basePath)) { delegateMatchers.addAll(getLinksMatchers(requestMatcherFactory, matcherProvider, basePath)); } + if (delegateMatchers.isEmpty()) { + return EMPTY_MATCHER; + } return new OrRequestMatcher(delegateMatchers); } private Stream streamPaths(List source, PathMappedEndpoints endpoints) { - return source.stream().filter(Objects::nonNull).map(this::getEndpointId).map(endpoints::getPath); + return source.stream() + .filter(Objects::nonNull) + .map(this::getEndpointId) + .map(endpoints::getPath) + .filter(Objects::nonNull); } @Override @@ -435,6 +442,7 @@ private static final class RequestMatcherFactory { RequestMatcher antPath(RequestMatcherProvider matcherProvider, String... parts) { StringBuilder pattern = new StringBuilder(); for (String part : parts) { + Assert.notNull(part, "'part' must not be null"); pattern.append(part); } return matcherProvider.getRequestMatcher(pattern.toString()); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java index 798ebf0067e9..797467f838c1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java @@ -875,7 +875,7 @@ static class CustomH2Driver extends org.h2.Driver { - org.springframework.boot.autoconfigure.flyway.FlywayAutoConfigurationTests$City + org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfigurationTests$City true diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6d3ea1268bd0..7bc046944426 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2063,7 +2063,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-amqp/releases/tag/v{version}") } } - library("Spring Authorization Server", "1.4.3-SNAPSHOT") { + library("Spring Authorization Server", "1.4.3") { considerSnapshots() group("org.springframework.security") { modules = [ @@ -2160,7 +2160,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-hateoas/releases/tag/{version}") } } - library("Spring Integration", "6.4.4-SNAPSHOT") { + library("Spring Integration", "6.4.4") { considerSnapshots() group("org.springframework.integration") { bom("spring-integration-bom") @@ -2175,7 +2175,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-integration/releases/tag/v{version}") } } - library("Spring Kafka", "3.3.5-SNAPSHOT") { + library("Spring Kafka", "3.3.5") { considerSnapshots() group("org.springframework.kafka") { modules = [ @@ -2213,7 +2213,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-ldap/releases/tag/{version}") } } - library("Spring Pulsar", "1.2.5-SNAPSHOT") { + library("Spring Pulsar", "1.2.5") { considerSnapshots() group("org.springframework.pulsar") { bom("spring-pulsar-bom") @@ -2271,7 +2271,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-security/releases/tag/{version}") } } - library("Spring Session", "3.4.3-SNAPSHOT") { + library("Spring Session", "3.4.3") { considerSnapshots() prohibit { startsWith(["Apple-", "Bean-", "Corn-", "Dragonfruit-"]) diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle index 250fe746f3fe..7f96367302f1 100644 --- a/spring-boot-project/spring-boot-docs/build.gradle +++ b/spring-boot-project/spring-boot-docs/build.gradle @@ -203,6 +203,7 @@ dokkatoo { } def aggregatedJavadoc = tasks.register('aggregatedJavadoc', Javadoc) { + dependsOn configurations.resolvedBom destinationDir = project.file(project.layout.buildDirectory.dir("docs/javadoc")) options { author = true diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc index f3e1d0d4f6bf..866f6fb1a52d 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc @@ -912,6 +912,9 @@ The following cache libraries are supported: * Any compliant JCache (JSR-107) implementation * Redis +WARNING: Metrics should be enabled for the auto-configuration to pick them up. +Refer to the documentation of the cache library you are using for more details. + Metrics are tagged by the name of the cache and by the name of the javadoc:org.springframework.cache.CacheManager[], which is derived from the bean name. NOTE: Only caches that are configured on startup are bound to the registry. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ApplicationResourceLoader.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ApplicationResourceLoader.java index 40a778ace1d9..63b6577272f1 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ApplicationResourceLoader.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ApplicationResourceLoader.java @@ -131,7 +131,7 @@ public static ResourceLoader get(ResourceLoader resourceLoader) { * class loader at the time this call is made. * @param resourceLoader the delegate resource loader * @param preferFileResolution if file based resolution is preferred when a suitable - * {@link ResourceFilePathResolver} support the resource + * {@link FilePathResolver} support the resource * @return a {@link ResourceLoader} instance * @since 3.4.1 */ @@ -160,8 +160,8 @@ private static ResourceLoader get(ResourceLoader resourceLoader, SpringFactories Assert.notNull(resourceLoader, "'resourceLoader' must not be null"); Assert.notNull(springFactoriesLoader, "'springFactoriesLoader' must not be null"); List protocolResolvers = springFactoriesLoader.load(ProtocolResolver.class); - List filePathResolvers = (preferFileResolution) - ? springFactoriesLoader.load(ResourceFilePathResolver.class) : Collections.emptyList(); + List filePathResolvers = (preferFileResolution) + ? springFactoriesLoader.load(FilePathResolver.class) : Collections.emptyList(); return new ProtocolResolvingResourceLoader(resourceLoader, protocolResolvers, filePathResolvers); } @@ -188,6 +188,28 @@ static ResourceLoader get(ClassLoader classLoader) { } + /** + * Strategy interface registered in {@code spring.factories} and used by + * {@link ApplicationResourceLoader} to determine the file path of loaded resource + * when it can also be represented as a {@link FileSystemResource}. + * + * @author Phillip Webb + * @since 3.4.5 + */ + public interface FilePathResolver { + + /** + * Return the {@code path} of the given resource if it can also be represented as + * a {@link FileSystemResource}. + * @param location the location used to create the resource + * @param resource the resource to check + * @return the file path of the resource or {@code null} if the it is not possible + * to represent the resource as a {@link FileSystemResource}. + */ + String resolveFilePath(String location, Resource resource); + + } + /** * An application {@link Resource}. */ @@ -214,10 +236,10 @@ private static class ProtocolResolvingResourceLoader implements ResourceLoader { private final List protocolResolvers; - private final List filePathResolvers; + private final List filePathResolvers; ProtocolResolvingResourceLoader(ResourceLoader resourceLoader, List protocolResolvers, - List filePathResolvers) { + List filePathResolvers) { this.resourceLoader = resourceLoader; this.protocolResolvers = protocolResolvers; this.filePathResolvers = filePathResolvers; @@ -239,12 +261,12 @@ public Resource getResource(String location) { } } Resource resource = this.resourceLoader.getResource(location); - String fileSystemPath = getFileSystemPath(location, resource); - return (fileSystemPath != null) ? new ApplicationResource(fileSystemPath) : resource; + String filePath = getFilePath(location, resource); + return (filePath != null) ? new ApplicationResource(filePath) : resource; } - private String getFileSystemPath(String location, Resource resource) { - for (ResourceFilePathResolver filePathResolver : this.filePathResolvers) { + private String getFilePath(String location, Resource resource) { + for (FilePathResolver filePathResolver : this.filePathResolvers) { String filePath = filePathResolver.resolveFilePath(location, resource); if (filePath != null) { return filePath; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ClassPathResourceFilePathResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ClassPathResourceFilePathResolver.java index aca69aaccb93..a5e891651902 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ClassPathResourceFilePathResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ClassPathResourceFilePathResolver.java @@ -16,16 +16,17 @@ package org.springframework.boot.io; +import org.springframework.boot.io.ApplicationResourceLoader.FilePathResolver; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; /** - * {@link ResourceFilePathResolver} for {@link ClassPathResource}. + * {@link FilePathResolver} for {@link ClassPathResource}. * * @author Phillip Webb */ -class ClassPathResourceFilePathResolver implements ResourceFilePathResolver { +class ClassPathResourceFilePathResolver implements ApplicationResourceLoader.FilePathResolver { @Override public String resolveFilePath(String location, Resource resource) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ResourceFilePathResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ResourceFilePathResolver.java deleted file mode 100644 index b3c9fe8b6ad8..000000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/io/ResourceFilePathResolver.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2025 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.io; - -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; - -/** - * Strategy interface registered in {@code spring.factories} and used by - * {@link ApplicationResourceLoader} to determine the file path of loaded resource when it - * can also be represented as a {@link FileSystemResource}. - * - * @author Phillip Webb - * @since 3.4.5 - */ -public interface ResourceFilePathResolver { - - /** - * Return the {@code path} of the given resource if it can also be represented as a - * {@link FileSystemResource}. - * @param location the location used to create the resource - * @param resource the resource to check - * @return the file path of the resource or {@code null} if the it is not possible to - * represent the resource as a {@link FileSystemResource}. - */ - String resolveFilePath(String location, Resource resource); - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/context/ServletContextResourceFilePathResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/context/ServletContextResourceFilePathResolver.java index 9c0e571d545d..4ed4a7ea4125 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/context/ServletContextResourceFilePathResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/context/ServletContextResourceFilePathResolver.java @@ -16,17 +16,18 @@ package org.springframework.boot.web.context; -import org.springframework.boot.io.ResourceFilePathResolver; +import org.springframework.boot.io.ApplicationResourceLoader; +import org.springframework.boot.io.ApplicationResourceLoader.FilePathResolver; import org.springframework.core.io.Resource; import org.springframework.util.ClassUtils; import org.springframework.web.context.support.ServletContextResource; /** - * {@link ResourceFilePathResolver} for {@link ServletContextResource}. + * {@link FilePathResolver} for {@link ServletContextResource}. * * @author Phillip Webb */ -class ServletContextResourceFilePathResolver implements ResourceFilePathResolver { +class ServletContextResourceFilePathResolver implements ApplicationResourceLoader.FilePathResolver { private static final String RESOURCE_CLASS_NAME = "org.springframework.web.context.support.ServletContextResource"; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/FilteredReactiveWebContextResourceFilePathResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/FilteredReactiveWebContextResourceFilePathResolver.java index 9876bc0aad95..4494cd35623d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/FilteredReactiveWebContextResourceFilePathResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/FilteredReactiveWebContextResourceFilePathResolver.java @@ -16,15 +16,16 @@ package org.springframework.boot.web.reactive.context; -import org.springframework.boot.io.ResourceFilePathResolver; +import org.springframework.boot.io.ApplicationResourceLoader; +import org.springframework.boot.io.ApplicationResourceLoader.FilePathResolver; import org.springframework.core.io.Resource; /** - * {@link ResourceFilePathResolver} for {@link FilteredReactiveWebContextResource}. + * {@link FilePathResolver} for {@link FilteredReactiveWebContextResource}. * * @author Dmytro Nosan */ -class FilteredReactiveWebContextResourceFilePathResolver implements ResourceFilePathResolver { +class FilteredReactiveWebContextResourceFilePathResolver implements ApplicationResourceLoader.FilePathResolver { @Override public String resolveFilePath(String location, Resource resource) { diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories index 6d99bfabd273..44b0c8c1bbff 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories @@ -107,7 +107,7 @@ org.springframework.core.io.ProtocolResolver=\ org.springframework.boot.io.Base64ProtocolResolver # Resource File Path Resolvers -org.springframework.boot.io.ResourceFilePathResolver=\ +org.springframework.boot.io.ApplicationResourceLoader$FilePathResolver=\ org.springframework.boot.io.ClassPathResourceFilePathResolver,\ org.springframework.boot.web.context.ServletContextResourceFilePathResolver,\ org.springframework.boot.web.reactive.context.FilteredReactiveWebContextResourceFilePathResolver