diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHint.java b/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHint.java index bb876e72c5c..bba58f28871 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ResourcePatternHint.java @@ -43,7 +43,8 @@ import org.springframework.util.Assert; * and its child directories at any depth. * * - *

A resource pattern must not start with a slash ({@code /}). + *

A resource pattern must not start with a slash ({@code /}) unless it is the + * root directory. * * @author Stephane Nicoll * @author Brian Clozel @@ -58,13 +59,16 @@ public final class ResourcePatternHint implements ConditionalHint { @Nullable private final TypeReference reachableType; + ResourcePatternHint(String pattern, @Nullable TypeReference reachableType) { - Assert.isTrue(!pattern.startsWith("/"), - () -> "Resource pattern [%s] must not start with a '/'".formatted(pattern)); + Assert.isTrue(("/".equals(pattern) || !pattern.startsWith("/")), + () -> "Resource pattern [%s] must not start with a '/' unless it is the root directory" + .formatted(pattern)); this.pattern = pattern; this.reachableType = reachableType; } + /** * Return the pattern to use for identifying the resources to match. * @return the pattern diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java index 0a01d0d6340..4e5f3d34cbd 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java @@ -81,6 +81,13 @@ class ResourceHintsTests { .hasSize(2); } + @Test + void registerRootDirectory() { + this.resourceHints.registerPattern("/"); + assertThat(this.resourceHints.resourcePatternHints()).singleElement().satisfies( + patternOf("/")); + } + @Test void registerPattern() { this.resourceHints.registerPattern("com/example/*.properties"); diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ResourcePatternHintTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ResourcePatternHintTests.java index e3ba055458a..303b243b2b7 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ResourcePatternHintTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ResourcePatternHintTests.java @@ -33,7 +33,15 @@ class ResourcePatternHintTests { void patternWithLeadingSlashIsRejected() { assertThatIllegalArgumentException() .isThrownBy(() -> new ResourcePatternHint("/file.properties", null)) - .withMessage("Resource pattern [/file.properties] must not start with a '/'"); + .withMessage("Resource pattern [/file.properties] must not start with a '/' unless it is the root directory"); + } + + @Test + void rootDirectory() { + ResourcePatternHint hint = new ResourcePatternHint("/", null); + assertThat(hint.toRegex().asMatchPredicate()) + .accepts("/") + .rejects("/com/example", "/file.txt"); } @Test