Skip to content

Commit 69d5587

Browse files
committed
Merge branch '6.1.x'
# Conflicts: # spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java
2 parents 52c4ffa + 1f6ab1a commit 69d5587

File tree

6 files changed

+75
-56
lines changed

6 files changed

+75
-56
lines changed

spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ else if (bean instanceof SmartLifecycle) {
409409
if (logger.isWarnEnabled()) {
410410
logger.warn("Failed to stop bean '" + beanName + "'", ex);
411411
}
412+
if (bean instanceof SmartLifecycle) {
413+
latch.countDown();
414+
}
412415
}
413416
}
414417
}

spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,35 @@
126126
*/
127127
String zone() default "";
128128

129+
/**
130+
* Execute the annotated method with a fixed period between invocations.
131+
* <p>The time unit is milliseconds by default but can be overridden via
132+
* {@link #timeUnit}.
133+
* @return the period
134+
*/
135+
long fixedRate() default -1;
136+
137+
/**
138+
* Execute the annotated method with a fixed period between invocations.
139+
* <p>The duration String can be in several formats:
140+
* <ul>
141+
* <li>a plain integer &mdash; which is interpreted to represent a duration in
142+
* milliseconds by default unless overridden via {@link #timeUnit()} (prefer
143+
* using {@link #fixedDelay()} in that case)</li>
144+
* <li>any of the known {@link org.springframework.format.annotation.DurationFormat.Style
145+
* DurationFormat.Style}: the {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 ISO8601}
146+
* style or the {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE SIMPLE} style
147+
* &mdash; using the {@link #timeUnit()} as fallback if the string doesn't contain an explicit unit</li>
148+
* <li>one of the above, with Spring-style "${...}" placeholders as well as SpEL expressions</li>
149+
* </ul>
150+
* @return the period as a String value &mdash; for example a placeholder,
151+
* or a {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 java.time.Duration} compliant value
152+
* or a {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE simple format} compliant value
153+
* @since 3.2.2
154+
* @see #fixedRate()
155+
*/
156+
String fixedRateString() default "";
157+
129158
/**
130159
* Execute the annotated method with a fixed period between the end of the
131160
* last invocation and the start of the next.
@@ -143,13 +172,13 @@
143172
* last invocation and the start of the next.
144173
* <p>The duration String can be in several formats:
145174
* <ul>
146-
* <li>a plain integer &mdash; which is interpreted to represent a duration in
147-
* milliseconds by default unless overridden via {@link #timeUnit()} (prefer
148-
* using {@link #fixedDelay()} in that case)</li>
149-
* <li>any of the known {@link org.springframework.format.annotation.DurationFormat.Style
150-
* DurationFormat.Style}: the {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 ISO8601}
151-
* style or the {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE SIMPLE} style
152-
* &mdash; using the {@link #timeUnit()} as fallback if the string doesn't contain an explicit unit</li>
175+
* <li>a plain integer &mdash; which is interpreted to represent a duration in
176+
* milliseconds by default unless overridden via {@link #timeUnit()} (prefer
177+
* using {@link #fixedDelay()} in that case)</li>
178+
* <li>any of the known {@link org.springframework.format.annotation.DurationFormat.Style
179+
* DurationFormat.Style}: the {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 ISO8601}
180+
* style or the {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE SIMPLE} style
181+
* &mdash; using the {@link #timeUnit()} as fallback if the string doesn't contain an explicit unit</li>
153182
* </ul>
154183
* <p><b>NOTE: With virtual threads, fixed rates and cron triggers are recommended
155184
* over fixed delays.</b> Fixed-delay tasks operate on a single scheduler thread
@@ -162,35 +191,6 @@
162191
*/
163192
String fixedDelayString() default "";
164193

165-
/**
166-
* Execute the annotated method with a fixed period between invocations.
167-
* <p>The time unit is milliseconds by default but can be overridden via
168-
* {@link #timeUnit}.
169-
* @return the period
170-
*/
171-
long fixedRate() default -1;
172-
173-
/**
174-
* Execute the annotated method with a fixed period between invocations.
175-
* <p>The duration String can be in several formats:
176-
* <ul>
177-
* <li>a plain integer &mdash; which is interpreted to represent a duration in
178-
* milliseconds by default unless overridden via {@link #timeUnit()} (prefer
179-
* using {@link #fixedDelay()} in that case)</li>
180-
* <li>any of the known {@link org.springframework.format.annotation.DurationFormat.Style
181-
* DurationFormat.Style}: the {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 ISO8601}
182-
* style or the {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE SIMPLE} style
183-
* &mdash; using the {@link #timeUnit()} as fallback if the string doesn't contain an explicit unit</li>
184-
* <li>one of the above, with Spring-style "${...}" placeholders as well as SpEL expressions</li>
185-
* </ul>
186-
* @return the period as a String value &mdash; for example a placeholder,
187-
* or a {@link org.springframework.format.annotation.DurationFormat.Style#ISO8601 java.time.Duration} compliant value
188-
* or a {@link org.springframework.format.annotation.DurationFormat.Style#SIMPLE simple format} compliant value
189-
* @since 3.2.2
190-
* @see #fixedRate()
191-
*/
192-
String fixedRateString() default "";
193-
194194
/**
195195
* Number of units of time to delay before the first execution of a
196196
* {@link #fixedRate} or {@link #fixedDelay} task.

spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.net.URLConnection;
3535
import java.nio.file.FileSystemNotFoundException;
3636
import java.nio.file.FileSystems;
37+
import java.nio.file.FileVisitOption;
3738
import java.nio.file.Files;
3839
import java.nio.file.Path;
3940
import java.util.Collections;
@@ -979,7 +980,7 @@ protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource
979980
.formatted(rootPath.toAbsolutePath(), subPattern));
980981
}
981982

982-
try (Stream<Path> files = Files.walk(rootPath)) {
983+
try (Stream<Path> files = Files.walk(rootPath, FileVisitOption.FOLLOW_LINKS)) {
983984
files.filter(isMatchingFile).sorted().map(FileSystemResource::new).forEach(result::add);
984985
}
985986
catch (Exception ex) {

spring-webmvc/src/main/java/org/springframework/web/servlet/function/RouterFunctions.java

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public static RouterFunction<ServerResponse> resource(RequestPredicate predicate
160160
*/
161161
public static RouterFunction<ServerResponse> resource(RequestPredicate predicate, Resource resource,
162162
BiConsumer<Resource, HttpHeaders> headersConsumer) {
163+
163164
return resources(new PredicateResourceLookupFunction(predicate, resource), headersConsumer);
164165
}
165166

@@ -197,6 +198,7 @@ public static RouterFunction<ServerResponse> resources(String pattern, Resource
197198
*/
198199
public static RouterFunction<ServerResponse> resources(String pattern, Resource location,
199200
BiConsumer<Resource, HttpHeaders> headersConsumer) {
201+
200202
return resources(resourceLookupFunction(pattern, location), headersConsumer);
201203
}
202204

@@ -240,7 +242,9 @@ public static RouterFunction<ServerResponse> resources(Function<ServerRequest, O
240242
* @return a router function that routes to resources
241243
* @since 6.1
242244
*/
243-
public static RouterFunction<ServerResponse> resources(Function<ServerRequest, Optional<Resource>> lookupFunction, BiConsumer<Resource, HttpHeaders> headersConsumer) {
245+
public static RouterFunction<ServerResponse> resources(Function<ServerRequest, Optional<Resource>> lookupFunction,
246+
BiConsumer<Resource, HttpHeaders> headersConsumer) {
247+
244248
return new ResourcesRouterFunction(lookupFunction, headersConsumer);
245249
}
246250

@@ -250,12 +254,12 @@ public static RouterFunction<ServerResponse> resources(Function<ServerRequest, O
250254
* can be used to change the {@code PathPatternParser} properties from the defaults, for instance to change
251255
* {@linkplain PathPatternParser#setCaseSensitive(boolean) case sensitivity}.
252256
* @param routerFunction the router function to change the parser in
253-
* @param parser the parser to change to.
257+
* @param parser the parser to change to
254258
* @param <T> the type of response returned by the handler function
255259
* @return the change router function
256260
*/
257-
public static <T extends ServerResponse> RouterFunction<T> changeParser(RouterFunction<T> routerFunction,
258-
PathPatternParser parser) {
261+
public static <T extends ServerResponse> RouterFunction<T> changeParser(
262+
RouterFunction<T> routerFunction, PathPatternParser parser) {
259263

260264
Assert.notNull(routerFunction, "RouterFunction must not be null");
261265
Assert.notNull(parser, "Parser must not be null");
@@ -1151,7 +1155,6 @@ public Optional<HandlerFunction<T>> route(ServerRequest request) {
11511155
public void accept(Visitor visitor) {
11521156
visitor.route(this.predicate, this.handlerFunction);
11531157
}
1154-
11551158
}
11561159

11571160

@@ -1173,13 +1176,10 @@ public Optional<HandlerFunction<T>> route(ServerRequest serverRequest) {
11731176
return this.predicate.nest(serverRequest)
11741177
.map(nestedRequest -> {
11751178
if (logger.isTraceEnabled()) {
1176-
logger.trace(
1177-
String.format(
1178-
"Nested predicate \"%s\" matches against \"%s\"",
1179-
this.predicate, serverRequest));
1179+
logger.trace(String.format("Nested predicate \"%s\" matches against \"%s\"",
1180+
this.predicate, serverRequest));
11801181
}
1181-
Optional<HandlerFunction<T>> result =
1182-
this.routerFunction.route(nestedRequest);
1182+
Optional<HandlerFunction<T>> result = this.routerFunction.route(nestedRequest);
11831183
if (result.isPresent() && nestedRequest != serverRequest) {
11841184
// new attributes map from nestedRequest.attributes() can be composed of the old attributes,
11851185
// which means that clearing the old attributes will remove those values from new attributes as well
@@ -1202,7 +1202,6 @@ public void accept(Visitor visitor) {
12021202
this.routerFunction.accept(visitor);
12031203
visitor.endNested(this.predicate);
12041204
}
1205-
12061205
}
12071206

12081207

@@ -1212,11 +1211,11 @@ private static class ResourcesRouterFunction extends AbstractRouterFunction<Serv
12121211

12131212
private final BiConsumer<Resource, HttpHeaders> headersConsumer;
12141213

1215-
12161214
public ResourcesRouterFunction(Function<ServerRequest, Optional<Resource>> lookupFunction,
12171215
BiConsumer<Resource, HttpHeaders> headersConsumer) {
1218-
Assert.notNull(lookupFunction, "Function must not be null");
1219-
Assert.notNull(headersConsumer, "HeadersConsumer must not be null");
1216+
1217+
Assert.notNull(lookupFunction, "Lookup function must not be null");
1218+
Assert.notNull(headersConsumer, "Headers consumer must not be null");
12201219
this.lookupFunction = lookupFunction;
12211220
this.headersConsumer = headersConsumer;
12221221
}
@@ -1284,5 +1283,4 @@ public RouterFunction<T> withAttributes(Consumer<Map<String, Object>> attributes
12841283
}
12851284
}
12861285

1287-
12881286
}

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MethodValidationTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.reflect.Method;
2020
import java.util.HashMap;
2121
import java.util.List;
22+
import java.util.Locale;
2223
import java.util.Set;
2324
import java.util.function.Consumer;
2425

@@ -28,10 +29,12 @@
2829
import jakarta.validation.constraints.Size;
2930
import jakarta.validation.executable.ExecutableValidator;
3031
import jakarta.validation.metadata.BeanDescriptor;
32+
import org.junit.jupiter.api.AfterEach;
3133
import org.junit.jupiter.api.BeforeEach;
3234
import org.junit.jupiter.api.Test;
3335

3436
import org.springframework.context.MessageSourceResolvable;
37+
import org.springframework.context.i18n.LocaleContextHolder;
3538
import org.springframework.http.MediaType;
3639
import org.springframework.http.converter.StringHttpMessageConverter;
3740
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@@ -91,6 +94,8 @@ class MethodValidationTests {
9194

9295
@BeforeEach
9396
void setup() throws Exception {
97+
LocaleContextHolder.setDefaultLocale(Locale.UK);
98+
9499
LocalValidatorFactoryBean validatorBean = new LocalValidatorFactoryBean();
95100
validatorBean.afterPropertiesSet();
96101
this.jakartaValidator = new InvocationCountingValidator(validatorBean);
@@ -120,6 +125,11 @@ private static RequestMappingHandlerAdapter initHandlerAdapter(Validator validat
120125
return handlerAdapter;
121126
}
122127

128+
@AfterEach
129+
void reset() {
130+
LocaleContextHolder.setDefaultLocale(null);
131+
}
132+
123133

124134
@Test
125135
void modelAttribute() {

spring-webmvc/src/test/java/org/springframework/web/servlet/tags/EvalTagTests.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222
import java.util.Map;
2323

2424
import jakarta.servlet.jsp.tagext.Tag;
25+
import org.junit.jupiter.api.AfterEach;
2526
import org.junit.jupiter.api.BeforeEach;
2627
import org.junit.jupiter.api.Test;
2728

29+
import org.springframework.context.i18n.LocaleContextHolder;
2830
import org.springframework.context.support.GenericApplicationContext;
2931
import org.springframework.core.env.MapPropertySource;
3032
import org.springframework.format.annotation.NumberFormat;
3133
import org.springframework.format.annotation.NumberFormat.Style;
32-
import org.springframework.format.number.PercentStyleFormatter;
3334
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
3435
import org.springframework.web.servlet.DispatcherServlet;
3536
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
@@ -49,6 +50,8 @@ class EvalTagTests extends AbstractTagTests {
4950

5051
@BeforeEach
5152
void setup() {
53+
LocaleContextHolder.setDefaultLocale(Locale.UK);
54+
5255
context = createPageContext();
5356
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
5457
factory.afterPropertiesSet();
@@ -58,6 +61,11 @@ void setup() {
5861
tag.setPageContext(context);
5962
}
6063

64+
@AfterEach
65+
void reset() {
66+
LocaleContextHolder.setDefaultLocale(null);
67+
}
68+
6169

6270
@Test
6371
void printScopedAttributeResult() throws Exception {
@@ -81,13 +89,12 @@ void printNullAsEmptyString() throws Exception {
8189

8290
@Test
8391
void printFormattedScopedAttributeResult() throws Exception {
84-
PercentStyleFormatter formatter = new PercentStyleFormatter();
8592
tag.setExpression("bean.formattable");
8693
int action = tag.doStartTag();
8794
assertThat(action).isEqualTo(Tag.EVAL_BODY_INCLUDE);
8895
action = tag.doEndTag();
8996
assertThat(action).isEqualTo(Tag.EVAL_PAGE);
90-
assertThat(((MockHttpServletResponse) context.getResponse()).getContentAsString()).isEqualTo(formatter.print(new BigDecimal(".25"), Locale.getDefault()));
97+
assertThat(((MockHttpServletResponse) context.getResponse()).getContentAsString()).isEqualTo("25%");
9198
}
9299

93100
@Test

0 commit comments

Comments
 (0)