@Scheduled supports java.time.Duration format for its delay attributes

Issue: SPR-15455
This commit is contained in:
Juergen Hoeller 2018-01-25 19:11:18 +01:00
parent ef3f93e84a
commit 13c735442c
3 changed files with 46 additions and 13 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 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,6 +86,7 @@ public @interface Scheduled {
* Execute the annotated method with a fixed period in milliseconds between the
* end of the last invocation and the start of the next.
* @return the delay in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String fixedDelayString() default "";
@ -101,6 +102,7 @@ public @interface Scheduled {
* Execute the annotated method with a fixed period in milliseconds between
* invocations.
* @return the period in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String fixedRateString() default "";
@ -117,6 +119,7 @@ public @interface Scheduled {
* Number of milliseconds to delay before the first execution of a
* {@link #fixedRate()} or {@link #fixedDelay()} task.
* @return the initial delay in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String initialDelayString() default "";

View File

@ -17,6 +17,7 @@
package org.springframework.scheduling.annotation;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -362,9 +363,9 @@ public class ScheduledAnnotationBeanPostProcessor
}
if (StringUtils.hasLength(initialDelayString)) {
try {
initialDelay = Long.parseLong(initialDelayString);
initialDelay = parseDelayAsLong(initialDelayString);
}
catch (NumberFormatException ex) {
catch (RuntimeException ex) {
throw new IllegalArgumentException(
"Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into long");
}
@ -414,9 +415,9 @@ public class ScheduledAnnotationBeanPostProcessor
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
try {
fixedDelay = Long.parseLong(fixedDelayString);
fixedDelay = parseDelayAsLong(fixedDelayString);
}
catch (NumberFormatException ex) {
catch (RuntimeException ex) {
throw new IllegalArgumentException(
"Invalid fixedDelayString value \"" + fixedDelayString + "\" - cannot parse into long");
}
@ -440,9 +441,9 @@ public class ScheduledAnnotationBeanPostProcessor
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
try {
fixedRate = Long.parseLong(fixedRateString);
fixedRate = parseDelayAsLong(fixedRateString);
}
catch (NumberFormatException ex) {
catch (RuntimeException ex) {
throw new IllegalArgumentException(
"Invalid fixedRateString value \"" + fixedRateString + "\" - cannot parse into long");
}
@ -469,6 +470,17 @@ public class ScheduledAnnotationBeanPostProcessor
}
}
private static long parseDelayAsLong(String value) throws RuntimeException {
if (value.length() > 1 && (isP(value.charAt(0)) || isP(value.charAt(1)))) {
return Duration.parse(value).toMillis();
}
return Long.parseLong(value);
}
private static boolean isP(char ch) {
return (ch == 'P' || ch == 'p');
}
/**
* Return all currently scheduled tasks, from {@link Scheduled} methods

View File

@ -425,12 +425,21 @@ public class ScheduledAnnotationBeanPostProcessorTests {
}
@Test
public void propertyPlaceholderWithFixedDelay() {
public void propertyPlaceholderWithFixedDelayInMillis() {
propertyPlaceholderWithFixedDelay(false);
}
@Test
public void propertyPlaceholderWithFixedDelayInDuration() {
propertyPlaceholderWithFixedDelay(true);
}
private void propertyPlaceholderWithFixedDelay(boolean durationFormat) {
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
Properties properties = new Properties();
properties.setProperty("fixedDelay", "5000");
properties.setProperty("initialDelay", "1000");
properties.setProperty("fixedDelay", (durationFormat ? "PT5S" : "5000"));
properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000"));
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedDelayTestBean.class);
context.registerBeanDefinition("postProcessor", processorDefinition);
@ -457,12 +466,21 @@ public class ScheduledAnnotationBeanPostProcessorTests {
}
@Test
public void propertyPlaceholderWithFixedRate() {
public void propertyPlaceholderWithFixedRateInMillis() {
propertyPlaceholderWithFixedRate(false);
}
@Test
public void propertyPlaceholderWithFixedRateInDuration() {
propertyPlaceholderWithFixedRate(true);
}
private void propertyPlaceholderWithFixedRate(boolean durationFormat) {
BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class);
BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
Properties properties = new Properties();
properties.setProperty("fixedRate", "3000");
properties.setProperty("initialDelay", "1000");
properties.setProperty("fixedRate", (durationFormat ? "PT3S" : "3000"));
properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000"));
placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties);
BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedRateTestBean.class);
context.registerBeanDefinition("postProcessor", processorDefinition);