Skip to content

Commit 13c7354

Browse files
committed
@scheduled supports java.time.Duration format for its delay attributes
Issue: SPR-15455
1 parent ef3f93e commit 13c7354

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -86,6 +86,7 @@
8686
* Execute the annotated method with a fixed period in milliseconds between the
8787
* end of the last invocation and the start of the next.
8888
* @return the delay in milliseconds as a String value, e.g. a placeholder
89+
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
8990
* @since 3.2.2
9091
*/
9192
String fixedDelayString() default "";
@@ -101,6 +102,7 @@
101102
* Execute the annotated method with a fixed period in milliseconds between
102103
* invocations.
103104
* @return the period in milliseconds as a String value, e.g. a placeholder
105+
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
104106
* @since 3.2.2
105107
*/
106108
String fixedRateString() default "";
@@ -117,6 +119,7 @@
117119
* Number of milliseconds to delay before the first execution of a
118120
* {@link #fixedRate()} or {@link #fixedDelay()} task.
119121
* @return the initial delay in milliseconds as a String value, e.g. a placeholder
122+
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
120123
* @since 3.2.2
121124
*/
122125
String initialDelayString() default "";

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.scheduling.annotation;
1818

1919
import java.lang.reflect.Method;
20+
import java.time.Duration;
2021
import java.util.ArrayList;
2122
import java.util.Collection;
2223
import java.util.Collections;
@@ -362,9 +363,9 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
362363
}
363364
if (StringUtils.hasLength(initialDelayString)) {
364365
try {
365-
initialDelay = Long.parseLong(initialDelayString);
366+
initialDelay = parseDelayAsLong(initialDelayString);
366367
}
367-
catch (NumberFormatException ex) {
368+
catch (RuntimeException ex) {
368369
throw new IllegalArgumentException(
369370
"Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into long");
370371
}
@@ -414,9 +415,9 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
414415
Assert.isTrue(!processedSchedule, errorMessage);
415416
processedSchedule = true;
416417
try {
417-
fixedDelay = Long.parseLong(fixedDelayString);
418+
fixedDelay = parseDelayAsLong(fixedDelayString);
418419
}
419-
catch (NumberFormatException ex) {
420+
catch (RuntimeException ex) {
420421
throw new IllegalArgumentException(
421422
"Invalid fixedDelayString value \"" + fixedDelayString + "\" - cannot parse into long");
422423
}
@@ -440,9 +441,9 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
440441
Assert.isTrue(!processedSchedule, errorMessage);
441442
processedSchedule = true;
442443
try {
443-
fixedRate = Long.parseLong(fixedRateString);
444+
fixedRate = parseDelayAsLong(fixedRateString);
444445
}
445-
catch (NumberFormatException ex) {
446+
catch (RuntimeException ex) {
446447
throw new IllegalArgumentException(
447448
"Invalid fixedRateString value \"" + fixedRateString + "\" - cannot parse into long");
448449
}
@@ -469,6 +470,17 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
469470
}
470471
}
471472

473+
private static long parseDelayAsLong(String value) throws RuntimeException {
474+
if (value.length() > 1 && (isP(value.charAt(0)) || isP(value.charAt(1)))) {
475+
return Duration.parse(value).toMillis();
476+
}
477+
return Long.parseLong(value);
478+
}
479+
480+
private static boolean isP(char ch) {
481+
return (ch == 'P' || ch == 'p');
482+
}
483+
472484

473485
/**
474486
* Return all currently scheduled tasks, from {@link Scheduled} methods

spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,21 @@ public void propertyPlaceholderWithCron() {
425425
}
426426

427427
@Test
428-
public void propertyPlaceholderWithFixedDelay() {
428+
public void propertyPlaceholderWithFixedDelayInMillis() {
429+
propertyPlaceholderWithFixedDelay(false);
430+
}
431+
432+
@Test
433+
public void propertyPlaceholderWithFixedDelayInDuration() {
434+
propertyPlaceholderWithFixedDelay(true);
435+
}
436+
437+
private void propertyPlaceholderWithFixedDelay(boolean durationFormat) {
429438
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
430439
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
431440
Properties properties = new Properties();
432-
properties.setProperty("fixedDelay", "5000");
433-
properties.setProperty("initialDelay", "1000");
441+
properties.setProperty("fixedDelay", (durationFormat ? "PT5S" : "5000"));
442+
properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000"));
434443
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
435444
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedDelayTestBean.class);
436445
context.registerBeanDefinition("postProcessor", processorDefinition);
@@ -457,12 +466,21 @@ public void propertyPlaceholderWithFixedDelay() {
457466
}
458467

459468
@Test
460-
public void propertyPlaceholderWithFixedRate() {
469+
public void propertyPlaceholderWithFixedRateInMillis() {
470+
propertyPlaceholderWithFixedRate(false);
471+
}
472+
473+
@Test
474+
public void propertyPlaceholderWithFixedRateInDuration() {
475+
propertyPlaceholderWithFixedRate(true);
476+
}
477+
478+
private void propertyPlaceholderWithFixedRate(boolean durationFormat) {
461479
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
462480
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
463481
Properties properties = new Properties();
464-
properties.setProperty("fixedRate", "3000");
465-
properties.setProperty("initialDelay", "1000");
482+
properties.setProperty("fixedRate", (durationFormat ? "PT3S" : "3000"));
483+
properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000"));
466484
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
467485
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedRateTestBean.class);
468486
context.registerBeanDefinition("postProcessor", processorDefinition);

0 commit comments

Comments
 (0)