diff --git a/spring-context/src/main/java/org/springframework/scheduling/TaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/TaskScheduler.java
index ad81312237e7..79be3a557299 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/TaskScheduler.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/TaskScheduler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -89,11 +89,8 @@ default Clock getClock() {
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @since 5.0
- * @see #schedule(Runnable, Date)
*/
- default ScheduledFuture> schedule(Runnable task, Instant startTime) {
- return schedule(task, Date.from(startTime));
- }
+ ScheduledFuture> schedule(Runnable task, Instant startTime);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time.
@@ -105,8 +102,12 @@ default ScheduledFuture> schedule(Runnable task, Instant startTime) {
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
+ * @deprecated as of 6.0, in favor of {@link #schedule(Runnable, Instant)}
*/
- ScheduledFuture> schedule(Runnable task, Date startTime);
+ @Deprecated
+ default ScheduledFuture> schedule(Runnable task, Date startTime) {
+ return schedule(task, startTime.toInstant());
+ }
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
@@ -121,11 +122,8 @@ default ScheduledFuture> schedule(Runnable task, Instant startTime) {
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @since 5.0
- * @see #scheduleAtFixedRate(Runnable, Date, long)
*/
- default ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
- return scheduleAtFixedRate(task, Date.from(startTime), period.toMillis());
- }
+ ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
@@ -139,8 +137,12 @@ default ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime,
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
+ * @deprecated as of 6.0, in favor of {@link #scheduleAtFixedRate(Runnable, Instant, Duration)}
*/
- ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, long period);
+ @Deprecated
+ default ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
+ return scheduleAtFixedRate(task, startTime.toInstant(), Duration.ofMillis(period));
+ }
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
@@ -153,11 +155,8 @@ default ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime,
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @since 5.0
- * @see #scheduleAtFixedRate(Runnable, long)
*/
- default ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
- return scheduleAtFixedRate(task, period.toMillis());
- }
+ ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
@@ -169,8 +168,12 @@ default ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
+ * @deprecated as of 6.0, in favor of {@link #scheduleAtFixedRate(Runnable, Duration)}
*/
- ScheduledFuture> scheduleAtFixedRate(Runnable task, long period);
+ @Deprecated
+ default ScheduledFuture> scheduleAtFixedRate(Runnable task, long period) {
+ return scheduleAtFixedRate(task, Duration.ofMillis(period));
+ }
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
@@ -186,11 +189,8 @@ default ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @since 5.0
- * @see #scheduleWithFixedDelay(Runnable, Date, long)
*/
- default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
- return scheduleWithFixedDelay(task, Date.from(startTime), delay.toMillis());
- }
+ ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
@@ -206,8 +206,12 @@ default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTi
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
+ * @deprecated as of 6.0, in favor of {@link #scheduleWithFixedDelay(Runnable, Instant, Duration)}
*/
- ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
+ @Deprecated
+ default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
+ return scheduleWithFixedDelay(task, startTime.toInstant(), Duration.ofMillis(delay));
+ }
/**
* Schedule the given {@link Runnable}, starting as soon as possible and invoking it with
@@ -220,11 +224,8 @@ default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTi
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @since 5.0
- * @see #scheduleWithFixedDelay(Runnable, long)
*/
- default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay) {
- return scheduleWithFixedDelay(task, delay.toMillis());
- }
+ ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and invoking it with
@@ -237,7 +238,11 @@ default ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
+ * @deprecated as of 6.0, in favor of {@link #scheduleWithFixedDelay(Runnable, Duration)}
*/
- ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay);
+ @Deprecated
+ default ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay) {
+ return scheduleWithFixedDelay(task, Duration.ofMillis(delay));
+ }
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/Trigger.java b/spring-context/src/main/java/org/springframework/scheduling/Trigger.java
index 16534514dc28..baf21776aff1 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/Trigger.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/Trigger.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.scheduling;
+import java.time.Instant;
import java.util.Date;
import org.springframework.lang.Nullable;
@@ -37,8 +38,24 @@ public interface Trigger {
* and last completion time
* @return the next execution time as defined by the trigger,
* or {@code null} if the trigger won't fire anymore
+ * @deprecated as of 6.0, in favor of {@link #nextExecution(TriggerContext)}
*/
+ @Deprecated
@Nullable
- Date nextExecutionTime(TriggerContext triggerContext);
+ default Date nextExecutionTime(TriggerContext triggerContext) {
+ Instant instant = nextExecution(triggerContext);
+ return instant != null ? Date.from(instant) : null;
+ }
+
+ /**
+ * Determine the next execution time according to the given trigger context.
+ * @param triggerContext context object encapsulating last execution times
+ * and last completion time
+ * @return the next execution time as defined by the trigger,
+ * or {@code null} if the trigger won't fire anymore
+ * @since 6.0
+ */
+ @Nullable
+ Instant nextExecution(TriggerContext triggerContext);
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/TriggerContext.java b/spring-context/src/main/java/org/springframework/scheduling/TriggerContext.java
index f50421eaa17d..933c1dde16da 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/TriggerContext.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/TriggerContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,6 +17,7 @@
package org.springframework.scheduling;
import java.time.Clock;
+import java.time.Instant;
import java.util.Date;
import org.springframework.lang.Nullable;
@@ -43,22 +44,59 @@ default Clock getClock() {
/**
* Return the last scheduled execution time of the task,
* or {@code null} if not scheduled before.
+ * @deprecated as of 6.0, in favor on {@link #lastScheduledExecution()}
*/
@Nullable
- Date lastScheduledExecutionTime();
+ @Deprecated
+ default Date lastScheduledExecutionTime() {
+ Instant instant = lastScheduledExecution();
+ return instant != null ? Date.from(instant) : null;
+ }
+
+ /**
+ * Return the last scheduled execution time of the task,
+ * or {@code null} if not scheduled before.
+ * @since 6.0
+ */
+ @Nullable
+ Instant lastScheduledExecution();
/**
* Return the last actual execution time of the task,
* or {@code null} if not scheduled before.
+ * @deprecated as of 6.0, in favor on {@link #lastActualExecution()}
*/
+ @Deprecated
@Nullable
- Date lastActualExecutionTime();
+ default Date lastActualExecutionTime() {
+ Instant instant = lastActualExecution();
+ return instant != null ? Date.from(instant) : null;
+ }
+
+ /**
+ * Return the last actual execution time of the task,
+ * or {@code null} if not scheduled before.
+ */
+ @Nullable
+ Instant lastActualExecution();
+
+ /**
+ * Return the last completion time of the task,
+ * or {@code null} if not scheduled before.
+ * @deprecated as of 6.0, in favor on {@link #lastCompletion()}
+ */
+ @Deprecated
+ @Nullable
+ default Date lastCompletionTime() {
+ Instant instant = lastCompletion();
+ return instant != null ? Date.from(instant) : null;
+ }
/**
* Return the last completion time of the task,
* or {@code null} if not scheduled before.
*/
@Nullable
- Date lastCompletionTime();
+ Instant lastCompletion();
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
index 23eb0de53b5b..f11feca15852 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
@@ -405,16 +405,16 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
Set tasks = new LinkedHashSet<>(4);
// Determine initial delay
- long initialDelay = convertToMillis(scheduled.initialDelay(), scheduled.timeUnit());
+ Duration initialDelay = toDuration(scheduled.initialDelay(), scheduled.timeUnit());
String initialDelayString = scheduled.initialDelayString();
if (StringUtils.hasText(initialDelayString)) {
- Assert.isTrue(initialDelay < 0, "Specify 'initialDelay' or 'initialDelayString', not both");
+ Assert.isTrue(initialDelay.isNegative(), "Specify 'initialDelay' or 'initialDelayString', not both");
if (this.embeddedValueResolver != null) {
initialDelayString = this.embeddedValueResolver.resolveStringValue(initialDelayString);
}
if (StringUtils.hasLength(initialDelayString)) {
try {
- initialDelay = convertToMillis(initialDelayString, scheduled.timeUnit());
+ initialDelay = toDuration(initialDelayString, scheduled.timeUnit());
}
catch (RuntimeException ex) {
throw new IllegalArgumentException(
@@ -432,7 +432,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
zone = this.embeddedValueResolver.resolveStringValue(zone);
}
if (StringUtils.hasLength(cron)) {
- Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");
+ Assert.isTrue(initialDelay.isNegative(), "'initialDelay' not supported for cron triggers");
processedSchedule = true;
if (!Scheduled.CRON_DISABLED.equals(cron)) {
TimeZone timeZone;
@@ -448,13 +448,13 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
}
// At this point we don't need to differentiate between initial delay set or not anymore
- if (initialDelay < 0) {
- initialDelay = 0;
+ if (initialDelay.isNegative()) {
+ initialDelay = Duration.ZERO;
}
// Check fixed delay
- long fixedDelay = convertToMillis(scheduled.fixedDelay(), scheduled.timeUnit());
- if (fixedDelay >= 0) {
+ Duration fixedDelay = toDuration(scheduled.fixedDelay(), scheduled.timeUnit());
+ if (!fixedDelay.isNegative()) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));
@@ -469,7 +469,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
try {
- fixedDelay = convertToMillis(fixedDelayString, scheduled.timeUnit());
+ fixedDelay = toDuration(fixedDelayString, scheduled.timeUnit());
}
catch (RuntimeException ex) {
throw new IllegalArgumentException(
@@ -480,8 +480,8 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
}
// Check fixed rate
- long fixedRate = convertToMillis(scheduled.fixedRate(), scheduled.timeUnit());
- if (fixedRate >= 0) {
+ Duration fixedRate = toDuration(scheduled.fixedRate(), scheduled.timeUnit());
+ if (!fixedRate.isNegative()) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));
@@ -495,7 +495,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean)
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
try {
- fixedRate = convertToMillis(fixedRateString, scheduled.timeUnit());
+ fixedRate = toDuration(fixedRateString, scheduled.timeUnit());
}
catch (RuntimeException ex) {
throw new IllegalArgumentException(
@@ -535,15 +535,15 @@ protected Runnable createRunnable(Object target, Method method) {
return new ScheduledMethodRunnable(target, invocableMethod);
}
- private static long convertToMillis(long value, TimeUnit timeUnit) {
- return TimeUnit.MILLISECONDS.convert(value, timeUnit);
+ private static Duration toDuration(long value, TimeUnit timeUnit) {
+ return Duration.of(value, timeUnit.toChronoUnit());
}
- private static long convertToMillis(String value, TimeUnit timeUnit) {
+ private static Duration toDuration(String value, TimeUnit timeUnit) {
if (isDurationString(value)) {
- return Duration.parse(value).toMillis();
+ return Duration.parse(value);
}
- return convertToMillis(Long.parseLong(value), timeUnit);
+ return toDuration(Long.parseLong(value), timeUnit);
}
private static boolean isDurationString(String value) {
diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java
index ca16b976e172..e96b035ba7f4 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ConcurrentTaskScheduler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,6 +17,8 @@
package org.springframework.scheduling.concurrent;
import java.time.Clock;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -32,7 +34,7 @@
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
-import org.springframework.scheduling.support.SimpleTriggerContext;
+import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -58,6 +60,7 @@
*
* @author Juergen Hoeller
* @author Mark Fisher
+ * @author Arjen Poutsma
* @since 3.0
* @see java.util.concurrent.ScheduledExecutorService
* @see java.util.concurrent.ScheduledThreadPoolExecutor
@@ -206,10 +209,10 @@ public ScheduledFuture> schedule(Runnable task, Trigger trigger) {
}
@Override
- public ScheduledFuture> schedule(Runnable task, Date startTime) {
- long initialDelay = startTime.getTime() - this.clock.millis();
+ public ScheduledFuture> schedule(Runnable task, Instant startTime) {
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return this.scheduledExecutor.schedule(decorateTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutor.schedule(decorateTask(task, false), initialDelay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
@@ -217,10 +220,10 @@ public ScheduledFuture> schedule(Runnable task, Date startTime) {
}
@Override
- public ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
- long initialDelay = startTime.getTime() - this.clock.millis();
+ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), initialDelay.toMillis(), period.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
@@ -228,9 +231,9 @@ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, lon
}
@Override
- public ScheduledFuture> scheduleAtFixedRate(Runnable task, long period) {
+ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
try {
- return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), 0, period, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutor.scheduleAtFixedRate(decorateTask(task, true), 0, period.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
@@ -238,10 +241,10 @@ public ScheduledFuture> scheduleAtFixedRate(Runnable task, long period) {
}
@Override
- public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
- long initialDelay = startTime.getTime() - this.clock.millis();
+ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), initialDelay.toMillis(), delay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
@@ -249,9 +252,9 @@ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime,
}
@Override
- public ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay) {
+ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay) {
try {
- return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
+ return this.scheduledExecutor.scheduleWithFixedDelay(decorateTask(task, true), 0, delay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
@@ -273,22 +276,66 @@ private Runnable decorateTask(Runnable task, boolean isRepeatingTask) {
*/
private class EnterpriseConcurrentTriggerScheduler {
- public ScheduledFuture> schedule(Runnable task, final Trigger trigger) {
+ public ScheduledFuture> schedule(Runnable task, Trigger trigger) {
ManagedScheduledExecutorService executor = (ManagedScheduledExecutorService) scheduledExecutor;
- return executor.schedule(task, new jakarta.enterprise.concurrent.Trigger() {
- @Override
+ return executor.schedule(task, new TriggerAdapter(trigger));
+ }
+
+ private static class TriggerAdapter implements jakarta.enterprise.concurrent.Trigger {
+
+ private final Trigger adaptee;
+
+
+ public TriggerAdapter(Trigger adaptee) {
+ this.adaptee = adaptee;
+ }
+
+ @Override
+ @Nullable
+ public Date getNextRunTime(@Nullable LastExecution le, Date taskScheduledTime) {
+ Instant instant = this.adaptee.nextExecution(new LastExecutionAdapter(le));
+ return instant != null ? Date.from(instant) : null;
+ }
+
+ @Nullable
+ private static Instant toInstant(@Nullable Date date) {
+ return date != null ? date.toInstant() : null;
+ }
+
+
+ @Override
+ public boolean skipRun(LastExecution lastExecutionInfo, Date scheduledRunTime) {
+ return false;
+ }
+
+ private static class LastExecutionAdapter implements TriggerContext {
+
@Nullable
- public Date getNextRunTime(@Nullable LastExecution le, Date taskScheduledTime) {
- return (trigger.nextExecutionTime(le != null ?
- new SimpleTriggerContext(le.getScheduledStart(), le.getRunStart(), le.getRunEnd()) :
- new SimpleTriggerContext()));
+ private final LastExecution le;
+
+
+ public LastExecutionAdapter(@Nullable LastExecution le) {
+ this.le = le;
+ }
+
+ @Override
+ public Instant lastScheduledExecution() {
+ return (this.le != null) ? toInstant(this.le.getScheduledStart()) : null;
}
+
+ @Override
+ public Instant lastActualExecution() {
+ return (this.le != null) ? toInstant(this.le.getRunStart()) : null;
+ }
+
@Override
- public boolean skipRun(LastExecution lastExecution, Date scheduledRunTime) {
- return false;
+ public Instant lastCompletion() {
+ return (this.le != null) ? toInstant(this.le.getRunEnd()) : null;
}
- });
+ }
}
+
+
}
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ReschedulingRunnable.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ReschedulingRunnable.java
index ca79c80fc6db..bb22d261d02a 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ReschedulingRunnable.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ReschedulingRunnable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,7 +17,8 @@
package org.springframework.scheduling.concurrent;
import java.time.Clock;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
@@ -56,7 +57,7 @@ class ReschedulingRunnable extends DelegatingErrorHandlingRunnable implements Sc
private ScheduledFuture> currentFuture;
@Nullable
- private Date scheduledExecutionTime;
+ private Instant scheduledExecutionTime;
private final Object triggerContextMonitor = new Object();
@@ -74,12 +75,12 @@ public ReschedulingRunnable(Runnable delegate, Trigger trigger, Clock clock,
@Nullable
public ScheduledFuture> schedule() {
synchronized (this.triggerContextMonitor) {
- this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
+ this.scheduledExecutionTime = this.trigger.nextExecution(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
- long initialDelay = this.scheduledExecutionTime.getTime() - this.triggerContext.getClock().millis();
- this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
+ Duration initialDelay = Duration.between(this.triggerContext.getClock().instant(), this.scheduledExecutionTime);
+ this.currentFuture = this.executor.schedule(this, initialDelay.toMillis(), TimeUnit.MILLISECONDS);
return this;
}
}
@@ -91,9 +92,9 @@ private ScheduledFuture> obtainCurrentFuture() {
@Override
public void run() {
- Date actualExecutionTime = new Date(this.triggerContext.getClock().millis());
+ Instant actualExecutionTime = this.triggerContext.getClock().instant();
super.run();
- Date completionTime = new Date(this.triggerContext.getClock().millis());
+ Instant completionTime = this.triggerContext.getClock().instant();
synchronized (this.triggerContextMonitor) {
Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
diff --git a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java
index 2688a853a5fb..fcc25e1e98c1 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.java
@@ -17,7 +17,8 @@
package org.springframework.scheduling.concurrent;
import java.time.Clock;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
@@ -377,11 +378,11 @@ public ScheduledFuture> schedule(Runnable task, Trigger trigger) {
}
@Override
- public ScheduledFuture> schedule(Runnable task, Date startTime) {
+ public ScheduledFuture> schedule(Runnable task, Instant startTime) {
ScheduledExecutorService executor = getScheduledExecutor();
- long initialDelay = startTime.getTime() - this.clock.millis();
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return executor.schedule(errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
+ return executor.schedule(errorHandlingTask(task, false), initialDelay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
@@ -389,11 +390,11 @@ public ScheduledFuture> schedule(Runnable task, Date startTime) {
}
@Override
- public ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
+ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
ScheduledExecutorService executor = getScheduledExecutor();
- long initialDelay = startTime.getTime() - this.clock.millis();
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
+ return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay.toMillis(), period.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
@@ -401,10 +402,10 @@ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Date startTime, lon
}
@Override
- public ScheduledFuture> scheduleAtFixedRate(Runnable task, long period) {
+ public ScheduledFuture> scheduleAtFixedRate(Runnable task, Duration period) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
- return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
+ return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
@@ -412,11 +413,11 @@ public ScheduledFuture> scheduleAtFixedRate(Runnable task, long period) {
}
@Override
- public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
+ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
ScheduledExecutorService executor = getScheduledExecutor();
- long initialDelay = startTime.getTime() - this.clock.millis();
+ Duration initialDelay = Duration.between(this.clock.instant(), startTime);
try {
- return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
+ return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay.toMillis(), delay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
@@ -424,10 +425,10 @@ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Date startTime,
}
@Override
- public ScheduledFuture> scheduleWithFixedDelay(Runnable task, long delay) {
+ public ScheduledFuture> scheduleWithFixedDelay(Runnable task, Duration delay) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
- return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
+ return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay.toMillis(), TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
diff --git a/spring-context/src/main/java/org/springframework/scheduling/config/FixedDelayTask.java b/spring-context/src/main/java/org/springframework/scheduling/config/FixedDelayTask.java
index 2aec5f308930..68f04bd682a6 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/config/FixedDelayTask.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/config/FixedDelayTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,10 +16,13 @@
package org.springframework.scheduling.config;
+import java.time.Duration;
+
/**
* Specialization of {@link IntervalTask} for fixed-delay semantics.
*
* @author Juergen Hoeller
+ * @author Arjen Poutsma
* @since 5.0.2
* @see org.springframework.scheduling.annotation.Scheduled#fixedDelay()
* @see ScheduledTaskRegistrar#addFixedDelayTask(IntervalTask)
@@ -31,9 +34,26 @@ public class FixedDelayTask extends IntervalTask {
* @param runnable the underlying task to execute
* @param interval how often in milliseconds the task should be executed
* @param initialDelay the initial delay before first execution of the task
+ * @deprecated as of 6.0, in favor on {@link #FixedDelayTask(Runnable, Duration, Duration)}
*/
+ @Deprecated
public FixedDelayTask(Runnable runnable, long interval, long initialDelay) {
super(runnable, interval, initialDelay);
}
+ /**
+ * Create a new {@code FixedDelayTask}.
+ * @param runnable the underlying task to execute
+ * @param interval how often the task should be executed
+ * @param initialDelay the initial delay before first execution of the task
+ * @since 6.0
+ */
+ public FixedDelayTask(Runnable runnable, Duration interval, Duration initialDelay) {
+ super(runnable, interval, initialDelay);
+ }
+
+ FixedDelayTask(IntervalTask task) {
+ super(task);
+ }
+
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/config/FixedRateTask.java b/spring-context/src/main/java/org/springframework/scheduling/config/FixedRateTask.java
index 0b16c574cdd0..73b7cf1707b5 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/config/FixedRateTask.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/config/FixedRateTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,10 +16,13 @@
package org.springframework.scheduling.config;
+import java.time.Duration;
+
/**
* Specialization of {@link IntervalTask} for fixed-rate semantics.
*
* @author Juergen Hoeller
+ * @author Arjen Poutsma
* @since 5.0.2
* @see org.springframework.scheduling.annotation.Scheduled#fixedRate()
* @see ScheduledTaskRegistrar#addFixedRateTask(IntervalTask)
@@ -31,9 +34,27 @@ public class FixedRateTask extends IntervalTask {
* @param runnable the underlying task to execute
* @param interval how often in milliseconds the task should be executed
* @param initialDelay the initial delay before first execution of the task
+ * @deprecated as of 6.0, in favor on {@link #FixedRateTask(Runnable, Duration, Duration)}
*/
+ @Deprecated
public FixedRateTask(Runnable runnable, long interval, long initialDelay) {
super(runnable, interval, initialDelay);
}
+ /**
+ * Create a new {@code FixedRateTask}.
+ * @param runnable the underlying task to execute
+ * @param interval how often the task should be executed
+ * @param initialDelay the initial delay before first execution of the task
+ * @since 6.0
+ */
+ public FixedRateTask(Runnable runnable, Duration interval, Duration initialDelay) {
+ super(runnable, interval, initialDelay);
+ }
+
+ FixedRateTask(IntervalTask task) {
+ super(task);
+ }
+
+
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/config/IntervalTask.java b/spring-context/src/main/java/org/springframework/scheduling/config/IntervalTask.java
index b259c7217aa3..dd9aeec54e06 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/config/IntervalTask.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/config/IntervalTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,21 +16,26 @@
package org.springframework.scheduling.config;
+import java.time.Duration;
+
+import org.springframework.util.Assert;
+
/**
* {@link Task} implementation defining a {@code Runnable} to be executed at a given
* millisecond interval which may be treated as fixed-rate or fixed-delay depending on
* context.
*
* @author Chris Beams
+ * @author Arjen Poutsma
* @since 3.2
* @see ScheduledTaskRegistrar#addFixedRateTask(IntervalTask)
* @see ScheduledTaskRegistrar#addFixedDelayTask(IntervalTask)
*/
public class IntervalTask extends Task {
- private final long interval;
+ private final Duration interval;
- private final long initialDelay;
+ private final Duration initialDelay;
/**
@@ -38,34 +43,95 @@ public class IntervalTask extends Task {
* @param runnable the underlying task to execute
* @param interval how often in milliseconds the task should be executed
* @param initialDelay the initial delay before first execution of the task
+ * @deprecated as of 6.0, in favor on {@link #IntervalTask(Runnable, Duration, Duration)}
*/
+ @Deprecated
public IntervalTask(Runnable runnable, long interval, long initialDelay) {
- super(runnable);
- this.interval = interval;
- this.initialDelay = initialDelay;
+ this(runnable, Duration.ofMillis(interval), Duration.ofMillis(initialDelay));
}
/**
* Create a new {@code IntervalTask} with no initial delay.
* @param runnable the underlying task to execute
* @param interval how often in milliseconds the task should be executed
+ * @deprecated as of 6.0, in favor on {@link #IntervalTask(Runnable, Duration)}
*/
+ @Deprecated
public IntervalTask(Runnable runnable, long interval) {
- this(runnable, interval, 0);
+ this(runnable, Duration.ofMillis(interval), Duration.ZERO);
+ }
+
+ /**
+ * Create a new {@code IntervalTask} with no initial delay.
+ * @param runnable the underlying task to execute
+ * @param interval how often the task should be executed
+ * @since 6.0
+ */
+ public IntervalTask(Runnable runnable, Duration interval) {
+ this(runnable, interval, Duration.ZERO);
+ }
+
+ /**
+ * Create a new {@code IntervalTask}.
+ * @param runnable the underlying task to execute
+ * @param interval how often the task should be executed
+ * @param initialDelay the initial delay before first execution of the task
+ * @since 6.0
+ */
+ public IntervalTask(Runnable runnable, Duration interval, Duration initialDelay) {
+ super(runnable);
+ Assert.notNull(interval, "Interval must not be null");
+ Assert.notNull(initialDelay, "InitialDelay must not be null");
+
+ this.interval = interval;
+ this.initialDelay = initialDelay;
+ }
+
+ /**
+ * Copy constructor.
+ */
+ IntervalTask(IntervalTask task) {
+ super(task.getRunnable());
+ Assert.notNull(task, "IntervalTask must not be null");
+
+ this.interval = task.getIntervalDuration();
+ this.initialDelay = task.getInitialDelayDuration();
}
+
+
/**
* Return how often in milliseconds the task should be executed.
+ * @deprecated as of 6.0, in favor of {@link #getIntervalDuration()}
*/
+ @Deprecated
public long getInterval() {
+ return this.interval.toMillis();
+ }
+
+ /**
+ * Return how often the task should be executed.
+ * @since 6.0
+ */
+ public Duration getIntervalDuration() {
return this.interval;
}
/**
* Return the initial delay before first execution of the task.
+ * @deprecated as of 6.0, in favor of {@link #getInitialDelayDuration()}
*/
+ @Deprecated
public long getInitialDelay() {
+ return this.initialDelay.toMillis();
+ }
+
+ /**
+ * Return the initial delay before first execution of the task.
+ * @since 6.0
+ */
+ public Duration getInitialDelayDuration() {
return this.initialDelay;
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/config/ScheduledTaskRegistrar.java b/spring-context/src/main/java/org/springframework/scheduling/config/ScheduledTaskRegistrar.java
index 3b9cc27aa16c..dd692b1374e9 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/config/ScheduledTaskRegistrar.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/config/ScheduledTaskRegistrar.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,9 +16,10 @@
package org.springframework.scheduling.config;
+import java.time.Duration;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -51,6 +52,7 @@
* @author Chris Beams
* @author Tobias Montagna-Hay
* @author Sam Brannen
+ * @author Arjen Poutsma
* @since 3.0
* @see org.springframework.scheduling.annotation.EnableAsync
* @see org.springframework.scheduling.annotation.SchedulingConfigurer
@@ -189,11 +191,11 @@ public List getCronTaskList() {
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-rate values.
- * @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
+ * @see TaskScheduler#scheduleAtFixedRate(Runnable, Duration)
*/
public void setFixedRateTasks(Map fixedRateTasks) {
this.fixedRateTasks = new ArrayList<>();
- fixedRateTasks.forEach(this::addFixedRateTask);
+ fixedRateTasks.forEach((task, interval) -> addFixedRateTask(task, Duration.ofMillis(interval)));
}
/**
@@ -218,11 +220,11 @@ public List getFixedRateTaskList() {
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
- * @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
+ * @see TaskScheduler#scheduleWithFixedDelay(Runnable, Duration)
*/
public void setFixedDelayTasks(Map fixedDelayTasks) {
this.fixedDelayTasks = new ArrayList<>();
- fixedDelayTasks.forEach(this::addFixedDelayTask);
+ fixedDelayTasks.forEach((task, delay) -> addFixedDelayTask(task, Duration.ofMillis(delay)));
}
/**
@@ -248,7 +250,7 @@ public List getFixedDelayTaskList() {
/**
* Add a Runnable task to be triggered per the given {@link Trigger}.
- * @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
+ * @see TaskScheduler#scheduleAtFixedRate(Runnable, Duration)
*/
public void addTriggerTask(Runnable task, Trigger trigger) {
addTriggerTask(new TriggerTask(task, trigger));
@@ -257,7 +259,7 @@ public void addTriggerTask(Runnable task, Trigger trigger) {
/**
* Add a {@code TriggerTask}.
* @since 3.2
- * @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
+ * @see TaskScheduler#scheduleAtFixedRate(Runnable, Duration)
*/
public void addTriggerTask(TriggerTask task) {
if (this.triggerTasks == null) {
@@ -290,16 +292,26 @@ public void addCronTask(CronTask task) {
/**
* Add a {@code Runnable} task to be triggered at the given fixed-rate interval.
- * @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
+ * @deprecated as of 6.0, in favor of {@link #addFixedRateTask(Runnable, Duration)}
*/
+ @Deprecated
public void addFixedRateTask(Runnable task, long interval) {
- addFixedRateTask(new IntervalTask(task, interval, 0));
+ addFixedRateTask(new IntervalTask(task, Duration.ofMillis(interval)));
+ }
+
+ /**
+ * Add a {@code Runnable} task to be triggered at the given fixed-rate interval.
+ * @since 6.0
+ * @see TaskScheduler#scheduleAtFixedRate(Runnable, Duration)
+ */
+ public void addFixedRateTask(Runnable task, Duration interval) {
+ addFixedRateTask(new IntervalTask(task, interval));
}
/**
* Add a fixed-rate {@link IntervalTask}.
* @since 3.2
- * @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
+ * @see TaskScheduler#scheduleAtFixedRate(Runnable, Duration)
*/
public void addFixedRateTask(IntervalTask task) {
if (this.fixedRateTasks == null) {
@@ -310,16 +322,26 @@ public void addFixedRateTask(IntervalTask task) {
/**
* Add a Runnable task to be triggered with the given fixed delay.
- * @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
+ * @deprecated as of 6.0, in favor of {@link #addFixedDelayTask(Runnable, Duration)}
*/
+ @Deprecated
public void addFixedDelayTask(Runnable task, long delay) {
- addFixedDelayTask(new IntervalTask(task, delay, 0));
+ addFixedDelayTask(new IntervalTask(task, Duration.ofMillis(delay)));
+ }
+
+ /**
+ * Add a Runnable task to be triggered with the given fixed delay.
+ * @since 6.0
+ * @see TaskScheduler#scheduleWithFixedDelay(Runnable, Duration)
+ */
+ public void addFixedDelayTask(Runnable task, Duration delay) {
+ addFixedDelayTask(new IntervalTask(task, delay));
}
/**
* Add a fixed-delay {@link IntervalTask}.
* @since 3.2
- * @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
+ * @see TaskScheduler#scheduleWithFixedDelay(Runnable, Duration)
*/
public void addFixedDelayTask(IntervalTask task) {
if (this.fixedDelayTasks == null) {
@@ -353,7 +375,6 @@ public void afterPropertiesSet() {
* Schedule all registered tasks against the underlying
* {@linkplain #setTaskScheduler(TaskScheduler) task scheduler}.
*/
- @SuppressWarnings("deprecation")
protected void scheduleTasks() {
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
@@ -371,12 +392,22 @@ protected void scheduleTasks() {
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
- addScheduledTask(scheduleFixedRateTask(task));
+ if (task instanceof FixedRateTask fixedRateTask) {
+ addScheduledTask(scheduleFixedRateTask(fixedRateTask));
+ }
+ else {
+ addScheduledTask(scheduleFixedRateTask(new FixedRateTask(task)));
+ }
}
}
if (this.fixedDelayTasks != null) {
for (IntervalTask task : this.fixedDelayTasks) {
- addScheduledTask(scheduleFixedDelayTask(task));
+ if (task instanceof FixedDelayTask fixedDelayTask) {
+ addScheduledTask(scheduleFixedDelayTask(fixedDelayTask));
+ }
+ else {
+ addScheduledTask(scheduleFixedDelayTask(new FixedDelayTask(task)));
+ }
}
}
}
@@ -437,22 +468,6 @@ public ScheduledTask scheduleCronTask(CronTask task) {
return (newTask ? scheduledTask : null);
}
- /**
- * Schedule the specified fixed-rate task, either right away if possible
- * or on initialization of the scheduler.
- * @return a handle to the scheduled task, allowing to cancel it
- * (or {@code null} if processing a previously registered task)
- * @since 4.3
- * @deprecated as of 5.0.2, in favor of {@link #scheduleFixedRateTask(FixedRateTask)}
- */
- @Deprecated
- @Nullable
- public ScheduledTask scheduleFixedRateTask(IntervalTask task) {
- FixedRateTask taskToUse = (task instanceof FixedRateTask ? (FixedRateTask) task :
- new FixedRateTask(task.getRunnable(), task.getInterval(), task.getInitialDelay()));
- return scheduleFixedRateTask(taskToUse);
- }
-
/**
* Schedule the specified fixed-rate task, either right away if possible
* or on initialization of the scheduler.
@@ -469,14 +484,15 @@ public ScheduledTask scheduleFixedRateTask(FixedRateTask task) {
newTask = true;
}
if (this.taskScheduler != null) {
- if (task.getInitialDelay() > 0) {
- Date startTime = new Date(this.taskScheduler.getClock().millis() + task.getInitialDelay());
+ Duration initialDelay = task.getInitialDelayDuration();
+ if (initialDelay.toMillis() > 0) {
+ Instant startTime = this.taskScheduler.getClock().instant().plus(initialDelay);
scheduledTask.future =
- this.taskScheduler.scheduleAtFixedRate(task.getRunnable(), startTime, task.getInterval());
+ this.taskScheduler.scheduleAtFixedRate(task.getRunnable(), startTime, task.getIntervalDuration());
}
else {
scheduledTask.future =
- this.taskScheduler.scheduleAtFixedRate(task.getRunnable(), task.getInterval());
+ this.taskScheduler.scheduleAtFixedRate(task.getRunnable(), task.getIntervalDuration());
}
}
else {
@@ -486,22 +502,6 @@ public ScheduledTask scheduleFixedRateTask(FixedRateTask task) {
return (newTask ? scheduledTask : null);
}
- /**
- * Schedule the specified fixed-delay task, either right away if possible
- * or on initialization of the scheduler.
- * @return a handle to the scheduled task, allowing to cancel it
- * (or {@code null} if processing a previously registered task)
- * @since 4.3
- * @deprecated as of 5.0.2, in favor of {@link #scheduleFixedDelayTask(FixedDelayTask)}
- */
- @Deprecated
- @Nullable
- public ScheduledTask scheduleFixedDelayTask(IntervalTask task) {
- FixedDelayTask taskToUse = (task instanceof FixedDelayTask ? (FixedDelayTask) task :
- new FixedDelayTask(task.getRunnable(), task.getInterval(), task.getInitialDelay()));
- return scheduleFixedDelayTask(taskToUse);
- }
-
/**
* Schedule the specified fixed-delay task, either right away if possible
* or on initialization of the scheduler.
@@ -518,14 +518,15 @@ public ScheduledTask scheduleFixedDelayTask(FixedDelayTask task) {
newTask = true;
}
if (this.taskScheduler != null) {
- if (task.getInitialDelay() > 0) {
- Date startTime = new Date(this.taskScheduler.getClock().millis() + task.getInitialDelay());
+ Duration initialDelay = task.getInitialDelayDuration();
+ if (!initialDelay.isNegative()) {
+ Instant startTime = this.taskScheduler.getClock().instant().plus(task.getInitialDelayDuration());
scheduledTask.future =
- this.taskScheduler.scheduleWithFixedDelay(task.getRunnable(), startTime, task.getInterval());
+ this.taskScheduler.scheduleWithFixedDelay(task.getRunnable(), startTime, task.getIntervalDuration());
}
else {
scheduledTask.future =
- this.taskScheduler.scheduleWithFixedDelay(task.getRunnable(), task.getInterval());
+ this.taskScheduler.scheduleWithFixedDelay(task.getRunnable(), task.getIntervalDuration());
}
}
else {
diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java b/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java
index 6581cdd61fe0..74399164a6b0 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,9 +16,9 @@
package org.springframework.scheduling.support;
+import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import java.util.Date;
import java.util.TimeZone;
import org.springframework.lang.Nullable;
@@ -93,23 +93,23 @@ public String getExpression() {
* previous execution; therefore, overlapping executions won't occur.
*/
@Override
- public Date nextExecutionTime(TriggerContext triggerContext) {
- Date date = triggerContext.lastCompletionTime();
- if (date != null) {
- Date scheduled = triggerContext.lastScheduledExecutionTime();
- if (scheduled != null && date.before(scheduled)) {
+ public Instant nextExecution(TriggerContext triggerContext) {
+ Instant instant = triggerContext.lastCompletion();
+ if (instant != null) {
+ Instant scheduled = triggerContext.lastScheduledExecution();
+ if (scheduled != null && instant.isBefore(scheduled)) {
// Previous task apparently executed too early...
// Let's simply use the last calculated execution time then,
// in order to prevent accidental re-fires in the same second.
- date = scheduled;
+ instant = scheduled;
}
}
else {
- date = new Date(triggerContext.getClock().millis());
+ instant = triggerContext.getClock().instant();
}
- ZonedDateTime dateTime = ZonedDateTime.ofInstant(date.toInstant(), this.zoneId);
+ ZonedDateTime dateTime = ZonedDateTime.ofInstant(instant, this.zoneId);
ZonedDateTime next = this.expression.next(dateTime);
- return (next != null ? Date.from(next.toInstant()) : null);
+ return (next != null ? next.toInstant() : null);
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/PeriodicTrigger.java b/spring-context/src/main/java/org/springframework/scheduling/support/PeriodicTrigger.java
index 9292c0086212..e13ca9489d31 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/support/PeriodicTrigger.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/support/PeriodicTrigger.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,7 +16,10 @@
package org.springframework.scheduling.support;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.springframework.lang.Nullable;
@@ -46,18 +49,22 @@
*/
public class PeriodicTrigger implements Trigger {
- private final long period;
+ private final Duration period;
- private final TimeUnit timeUnit;
+ @Nullable
+ private final ChronoUnit chronoUnit;
- private volatile long initialDelay;
+ @Nullable
+ private volatile Duration initialDelay;
private volatile boolean fixedRate;
/**
* Create a trigger with the given period in milliseconds.
+ * @deprecated as of 6.0, in favor on {@link #PeriodicTrigger(Duration)}
*/
+ @Deprecated
public PeriodicTrigger(long period) {
this(period, null);
}
@@ -66,44 +73,132 @@ public PeriodicTrigger(long period) {
* Create a trigger with the given period and time unit. The time unit will
* apply not only to the period but also to any 'initialDelay' value, if
* configured on this Trigger later via {@link #setInitialDelay(long)}.
+ * @deprecated as of 6.0, in favor on {@link #PeriodicTrigger(Duration)}
*/
+ @Deprecated
public PeriodicTrigger(long period, @Nullable TimeUnit timeUnit) {
- Assert.isTrue(period >= 0, "period must not be negative");
- this.timeUnit = (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS);
- this.period = this.timeUnit.toMillis(period);
+ this(toDuration(period, timeUnit), timeUnit);
+ }
+
+ private static Duration toDuration(long amount, @Nullable TimeUnit timeUnit) {
+ if (timeUnit != null) {
+ return Duration.of(amount, timeUnit.toChronoUnit());
+ }
+ else {
+ return Duration.ofMillis(amount);
+ }
+ }
+
+ /**
+ * Create a trigger with the given period as a duration.
+ * @since 6.0
+ */
+ public PeriodicTrigger(Duration period) {
+ this(period, null);
+ }
+
+ private PeriodicTrigger(Duration period, @Nullable TimeUnit timeUnit) {
+ Assert.notNull(period, "Period must not be null");
+ Assert.isTrue(!period.isNegative(), "Period must not be negative");
+ this.period = period;
+ if (timeUnit != null) {
+ this.chronoUnit = timeUnit.toChronoUnit();
+ }
+ else {
+ this.chronoUnit = null;
+ }
}
/**
* Return this trigger's period.
* @since 5.0.2
+ * @deprecated as of 6.0, in favor on {@link #getPeriodDuration()}
*/
+ @Deprecated
public long getPeriod() {
+ if (this.chronoUnit != null) {
+ return this.period.get(this.chronoUnit);
+ }
+ else {
+ return this.period.toMillis();
+ }
+ }
+
+ /**
+ * Return this trigger's period.
+ * @since 6.0
+ */
+ public Duration getPeriodDuration() {
return this.period;
}
/**
* Return this trigger's time unit (milliseconds by default).
* @since 5.0.2
+ * @deprecated as of 6.0, with no direct replacement
*/
+ @Deprecated
public TimeUnit getTimeUnit() {
- return this.timeUnit;
+ if (this.chronoUnit != null) {
+ return TimeUnit.of(this.chronoUnit);
+ }
+ else {
+ return TimeUnit.MILLISECONDS;
+ }
}
/**
* Specify the delay for the initial execution. It will be evaluated in
* terms of this trigger's {@link TimeUnit}. If no time unit was explicitly
* provided upon instantiation, the default is milliseconds.
+ * @deprecated as of 6.0, in favor of {@link #setInitialDelay(Duration)}
*/
+ @Deprecated
public void setInitialDelay(long initialDelay) {
- this.initialDelay = this.timeUnit.toMillis(initialDelay);
+ if (this.chronoUnit != null) {
+ this.initialDelay = Duration.of(initialDelay, this.chronoUnit);
+ }
+ else {
+ this.initialDelay = Duration.ofMillis(initialDelay);
+ }
+ }
+
+ /**
+ * Specify the delay for the initial execution.
+ * @since 6.0
+ */
+ public void setInitialDelay(Duration initialDelay) {
+ this.initialDelay = initialDelay;
}
/**
* Return the initial delay, or 0 if none.
* @since 5.0.2
+ * @deprecated as of 6.0, in favor on {@link #getInitialDelayDuration()}
*/
+ @Deprecated
public long getInitialDelay() {
+ Duration initialDelay = this.initialDelay;
+ if (initialDelay != null) {
+ if (this.chronoUnit != null) {
+ return initialDelay.get(this.chronoUnit);
+ }
+ else {
+ return initialDelay.toMillis();
+ }
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return the initial delay, or {@code null} if none.
+ * @since 6.0
+ */
+ @Nullable
+ public Duration getInitialDelayDuration() {
return this.initialDelay;
}
@@ -130,16 +225,23 @@ public boolean isFixedRate() {
* Returns the time after which a task should run again.
*/
@Override
- public Date nextExecutionTime(TriggerContext triggerContext) {
- Date lastExecution = triggerContext.lastScheduledExecutionTime();
- Date lastCompletion = triggerContext.lastCompletionTime();
+ public Instant nextExecution(TriggerContext triggerContext) {
+ Instant lastExecution = triggerContext.lastScheduledExecution();
+ Instant lastCompletion = triggerContext.lastCompletion();
if (lastExecution == null || lastCompletion == null) {
- return new Date(triggerContext.getClock().millis() + this.initialDelay);
+ Instant instant = triggerContext.getClock().instant();
+ Duration initialDelay = this.initialDelay;
+ if (initialDelay == null) {
+ return instant;
+ }
+ else {
+ return instant.plus(initialDelay);
+ }
}
if (this.fixedRate) {
- return new Date(lastExecution.getTime() + this.period);
+ return lastExecution.plus(this.period);
}
- return new Date(lastCompletion.getTime() + this.period);
+ return lastCompletion.plus(this.period);
}
@@ -151,13 +253,14 @@ public boolean equals(@Nullable Object other) {
if (!(other instanceof PeriodicTrigger otherTrigger)) {
return false;
}
- return (this.fixedRate == otherTrigger.fixedRate && this.initialDelay == otherTrigger.initialDelay &&
- this.period == otherTrigger.period);
+ return (this.fixedRate == otherTrigger.fixedRate &&
+ this.period.equals(otherTrigger.period) &&
+ Objects.equals(this.initialDelay, otherTrigger.initialDelay));
}
@Override
public int hashCode() {
- return (this.fixedRate ? 17 : 29) + (int) (37 * this.period) + (int) (41 * this.initialDelay);
+ return this.period.hashCode();
}
}
diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/SimpleTriggerContext.java b/spring-context/src/main/java/org/springframework/scheduling/support/SimpleTriggerContext.java
index 2c647c34c88f..d6fe019afde5 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/support/SimpleTriggerContext.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/support/SimpleTriggerContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,6 +17,7 @@
package org.springframework.scheduling.support;
import java.time.Clock;
+import java.time.Instant;
import java.util.Date;
import org.springframework.lang.Nullable;
@@ -33,13 +34,13 @@ public class SimpleTriggerContext implements TriggerContext {
private final Clock clock;
@Nullable
- private volatile Date lastScheduledExecutionTime;
+ private volatile Instant lastScheduledExecution;
@Nullable
- private volatile Date lastActualExecutionTime;
+ private volatile Instant lastActualExecution;
@Nullable
- private volatile Date lastCompletionTime;
+ private volatile Instant lastCompletion;
/**
@@ -56,12 +57,34 @@ public SimpleTriggerContext() {
* @param lastScheduledExecutionTime last scheduled execution time
* @param lastActualExecutionTime last actual execution time
* @param lastCompletionTime last completion time
+ * @deprecated as of 6.0, in favor of {@link #SimpleTriggerContext(Instant, Instant, Instant)}
*/
- public SimpleTriggerContext(Date lastScheduledExecutionTime, Date lastActualExecutionTime, Date lastCompletionTime) {
+ @Deprecated
+ public SimpleTriggerContext(@Nullable Date lastScheduledExecutionTime, @Nullable Date lastActualExecutionTime,
+ @Nullable Date lastCompletionTime) {
+
+ this(toInstant(lastScheduledExecutionTime), toInstant(lastActualExecutionTime), toInstant(lastCompletionTime));
+ }
+
+ @Nullable
+ private static Instant toInstant(@Nullable Date date) {
+ return date != null ? date.toInstant() : null;
+ }
+
+ /**
+ * Create a SimpleTriggerContext with the given time values,
+ * exposing the system clock for the default time zone.
+ * @param lastScheduledExecution last scheduled execution time
+ * @param lastActualExecution last actual execution time
+ * @param lastCompletion last completion time
+ */
+ public SimpleTriggerContext(@Nullable Instant lastScheduledExecution, @Nullable Instant lastActualExecution,
+ @Nullable Instant lastCompletion) {
+
this();
- this.lastScheduledExecutionTime = lastScheduledExecutionTime;
- this.lastActualExecutionTime = lastActualExecutionTime;
- this.lastCompletionTime = lastCompletionTime;
+ this.lastScheduledExecution = lastScheduledExecution;
+ this.lastActualExecution = lastActualExecution;
+ this.lastCompletion = lastCompletion;
}
/**
@@ -69,7 +92,7 @@ public SimpleTriggerContext(Date lastScheduledExecutionTime, Date lastActualExec
* exposing the given clock.
* @param clock the clock to use for trigger calculation
* @since 5.3
- * @see #update(Date, Date, Date)
+ * @see #update(Instant, Instant, Instant)
*/
public SimpleTriggerContext(Clock clock) {
this.clock = clock;
@@ -81,11 +104,27 @@ public SimpleTriggerContext(Clock clock) {
* @param lastScheduledExecutionTime last scheduled execution time
* @param lastActualExecutionTime last actual execution time
* @param lastCompletionTime last completion time
+ * @deprecated as of 6.0, in favor of {@link #update(Instant, Instant, Instant)}
*/
- public void update(Date lastScheduledExecutionTime, Date lastActualExecutionTime, Date lastCompletionTime) {
- this.lastScheduledExecutionTime = lastScheduledExecutionTime;
- this.lastActualExecutionTime = lastActualExecutionTime;
- this.lastCompletionTime = lastCompletionTime;
+ @Deprecated
+ public void update(@Nullable Date lastScheduledExecutionTime, @Nullable Date lastActualExecutionTime,
+ @Nullable Date lastCompletionTime) {
+
+ update(toInstant(lastScheduledExecutionTime), toInstant(lastActualExecutionTime), toInstant(lastCompletionTime));
+ }
+
+ /**
+ * Update this holder's state with the latest time values.
+ * @param lastScheduledExecution last scheduled execution time
+ * @param lastActualExecution last actual execution time
+ * @param lastCompletion last completion time
+ */
+ public void update(@Nullable Instant lastScheduledExecution, @Nullable Instant lastActualExecution,
+ @Nullable Instant lastCompletion) {
+
+ this.lastScheduledExecution = lastScheduledExecution;
+ this.lastActualExecution = lastActualExecution;
+ this.lastCompletion = lastCompletion;
}
@@ -96,20 +135,20 @@ public Clock getClock() {
@Override
@Nullable
- public Date lastScheduledExecutionTime() {
- return this.lastScheduledExecutionTime;
+ public Instant lastScheduledExecution() {
+ return this.lastScheduledExecution;
}
@Override
@Nullable
- public Date lastActualExecutionTime() {
- return this.lastActualExecutionTime;
+ public Instant lastActualExecution() {
+ return this.lastActualExecution;
}
@Override
@Nullable
- public Date lastCompletionTime() {
- return this.lastCompletionTime;
+ public Instant lastCompletion() {
+ return this.lastCompletion;
}
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java
index 28bdafd59f88..a67e98ee503b 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,8 +16,10 @@
package org.springframework.scheduling.annotation;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
-import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.AfterEach;
@@ -176,7 +178,7 @@ static class FixedRateTaskConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
- taskRegistrar.addFixedRateTask(() -> {}, 100);
+ taskRegistrar.addFixedRateTask(() -> {}, Duration.ofMillis(100));
}
@Bean
@@ -423,7 +425,7 @@ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
taskRegistrar.addFixedRateTask(new IntervalTask(
() -> worker().executedByThread = Thread.currentThread().getName(),
- 10, 0));
+ Duration.ofMillis(10)));
}
}
@@ -441,7 +443,7 @@ public TaskScheduler scheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.initialize();
scheduler.schedule(() -> counter().incrementAndGet(),
- triggerContext -> new Date(new Date().getTime()+10));
+ triggerContext -> Instant.now().plus(10, ChronoUnit.MILLIS));
return scheduler;
}
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java
index 9aaf52c881f3..81f6ec104907 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -22,13 +22,14 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
-import java.util.Calendar;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterEach;
@@ -118,8 +119,8 @@ void fixedDelayTask(@NameToClass Class> beanClass, long expectedInterval) {
Method targetMethod = runnable.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedDelay");
- assertThat(task.getInitialDelay()).isEqualTo(0L);
- assertThat(task.getInterval()).isEqualTo(expectedInterval);
+ assertThat(task.getInitialDelayDuration()).isZero();
+ assertThat(task.getIntervalDuration()).isEqualTo(Duration.ofMillis(expectedInterval));
}
@ParameterizedTest
@@ -152,8 +153,8 @@ void fixedRateTask(@NameToClass Class> beanClass, long expectedInterval) {
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedRate");
assertSoftly(softly -> {
- softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(0);
- softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval);
+ softly.assertThat(task.getInitialDelayDuration()).as("initial delay").isZero();
+ softly.assertThat(task.getIntervalDuration()).as("interval").isEqualTo(Duration.ofMillis(expectedInterval));
});
}
@@ -187,8 +188,8 @@ void fixedRateTaskWithInitialDelay(@NameToClass Class> beanClass, long expecte
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedRate");
assertSoftly(softly -> {
- softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay);
- softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval);
+ softly.assertThat(task.getInitialDelayDuration()).as("initial delay").isEqualTo(Duration.ofMillis(expectedInitialDelay));
+ softly.assertThat(task.getIntervalDuration()).as("interval").isEqualTo(Duration.ofMillis(expectedInterval));
});
}
@@ -251,16 +252,16 @@ private void severalFixedRates(StaticApplicationContext context,
Method targetMethod = runnable1.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedRate");
- assertThat(task1.getInitialDelay()).isEqualTo(0);
- assertThat(task1.getInterval()).isEqualTo(4_000L);
+ assertThat(task1.getInitialDelayDuration()).isZero();
+ assertThat(task1.getIntervalDuration()).isEqualTo(Duration.ofMillis(4_000L));
IntervalTask task2 = fixedRateTasks.get(1);
ScheduledMethodRunnable runnable2 = (ScheduledMethodRunnable) task2.getRunnable();
targetObject = runnable2.getTarget();
targetMethod = runnable2.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedRate");
- assertThat(task2.getInitialDelay()).isEqualTo(2_000L);
- assertThat(task2.getInterval()).isEqualTo(4_000L);
+ assertThat(task2.getInitialDelayDuration()).isEqualTo(Duration.ofMillis(2_000L));
+ assertThat(task2.getIntervalDuration()).isEqualTo(Duration.ofMillis(4_000L));
}
@Test
@@ -320,20 +321,20 @@ void cronTaskWithZone() {
boolean condition = trigger instanceof CronTrigger;
assertThat(condition).isTrue();
CronTrigger cronTrigger = (CronTrigger) trigger;
- Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+10"));
- cal.clear();
- cal.set(2013, 3, 15, 4, 0); // 15-04-2013 4:00 GMT+10
- Date lastScheduledExecutionTime = cal.getTime();
- Date lastActualExecutionTime = cal.getTime();
- cal.add(Calendar.MINUTE, 30); // 4:30
- Date lastCompletionTime = cal.getTime();
+ ZonedDateTime dateTime = ZonedDateTime.of(2013, 4, 15, 4, 0, 0, 0, ZoneId.of("GMT+10"));
+// Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+10"));
+// cal.clear();
+// cal.set(2013, 3, 15, 4, 0); // 15-04-2013 4:00 GMT+10;
+ Instant lastScheduledExecution = dateTime.toInstant();
+ Instant lastActualExecution = dateTime.toInstant();
+ dateTime = dateTime.plusMinutes(30);
+ Instant lastCompletion = dateTime.toInstant();
TriggerContext triggerContext = new SimpleTriggerContext(
- lastScheduledExecutionTime, lastActualExecutionTime, lastCompletionTime);
- cal.add(Calendar.MINUTE, 30);
- cal.add(Calendar.HOUR_OF_DAY, 1); // 6:00
- Date nextExecutionTime = cronTrigger.nextExecutionTime(triggerContext);
+ lastScheduledExecution, lastActualExecution, lastCompletion);
+ dateTime = dateTime.plusMinutes(90); // 6:00
+ Instant nextExecutionTime = cronTrigger.nextExecution(triggerContext);
// assert that 6:00 is next execution time
- assertThat(nextExecutionTime).isEqualTo(cal.getTime());
+ assertThat(nextExecutionTime).isEqualTo(dateTime.toInstant());
}
@Test
@@ -407,7 +408,7 @@ void metaAnnotationWithFixedRate() {
Method targetMethod = runnable.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("checkForUpdates");
- assertThat(task.getInterval()).isEqualTo(5_000L);
+ assertThat(task.getIntervalDuration()).isEqualTo(Duration.ofMillis(5_000L));
}
@Test
@@ -434,8 +435,8 @@ void composedAnnotationWithInitialDelayAndFixedRate() {
Method targetMethod = runnable.getMethod();
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("checkForUpdates");
- assertThat(task.getInterval()).isEqualTo(5_000L);
- assertThat(task.getInitialDelay()).isEqualTo(1_000L);
+ assertThat(task.getIntervalDuration()).isEqualTo(Duration.ofMillis(5_000L));
+ assertThat(task.getInitialDelayDuration()).isEqualTo(Duration.ofMillis(1_000L));
}
@Test
@@ -555,8 +556,8 @@ void propertyPlaceholderWithFixedDelay(@NameToClass Class> beanClass, String f
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedDelay");
assertSoftly(softly -> {
- softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay);
- softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval);
+ softly.assertThat(task.getInitialDelayDuration()).as("initial delay").isEqualTo(Duration.ofMillis(expectedInitialDelay));
+ softly.assertThat(task.getIntervalDuration()).as("interval").isEqualTo(Duration.ofMillis(expectedInterval));
});
}
@@ -599,8 +600,8 @@ void propertyPlaceholderWithFixedRate(@NameToClass Class> beanClass, String fi
assertThat(targetObject).isEqualTo(target);
assertThat(targetMethod.getName()).isEqualTo("fixedRate");
assertSoftly(softly -> {
- softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay);
- softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval);
+ softly.assertThat(task.getInitialDelayDuration()).as("initial delay").isEqualTo(Duration.ofMillis(expectedInitialDelay));
+ softly.assertThat(task.getIntervalDuration()).as("interval").isEqualTo(Duration.ofMillis(expectedInterval));
});
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskSchedulerTests.java b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskSchedulerTests.java
index a96544640628..7109ffea52c7 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskSchedulerTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/concurrent/ThreadPoolTaskSchedulerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.scheduling.concurrent;
+import java.time.Instant;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@@ -182,11 +183,11 @@ private static class TestTrigger implements Trigger {
}
@Override
- public Date nextExecutionTime(TriggerContext triggerContext) {
+ public Instant nextExecution(TriggerContext triggerContext) {
if (this.actualRunCount.incrementAndGet() > this.maxRunCount) {
return null;
}
- return new Date();
+ return Instant.now();
}
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/config/ScheduledTasksBeanDefinitionParserTests.java b/spring-context/src/test/java/org/springframework/scheduling/config/ScheduledTasksBeanDefinitionParserTests.java
index 16879f1e7961..dde3a4faa6d4 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/config/ScheduledTasksBeanDefinitionParserTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/config/ScheduledTasksBeanDefinitionParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,7 +17,8 @@
package org.springframework.scheduling.config;
import java.lang.reflect.Method;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
@@ -78,28 +79,28 @@ public void checkTarget() {
public void fixedRateTasks() {
List tasks = (List) new DirectFieldAccessor(
this.registrar).getPropertyValue("fixedRateTasks");
- assertThat(tasks.size()).isEqualTo(3);
- assertThat(tasks.get(0).getInterval()).isEqualTo(1000L);
- assertThat(tasks.get(1).getInterval()).isEqualTo(2000L);
- assertThat(tasks.get(2).getInterval()).isEqualTo(4000L);
- assertThat(tasks.get(2).getInitialDelay()).isEqualTo(500);
+ assertThat(tasks).hasSize(3);
+ assertThat(tasks.get(0).getIntervalDuration()).isEqualTo(Duration.ofMillis(1000L));
+ assertThat(tasks.get(1).getIntervalDuration()).isEqualTo(Duration.ofMillis(2000L));
+ assertThat(tasks.get(2).getIntervalDuration()).isEqualTo(Duration.ofMillis(4000L));
+ assertThat(tasks.get(2).getInitialDelayDuration()).isEqualTo(Duration.ofMillis(500));
}
@Test
public void fixedDelayTasks() {
List tasks = (List) new DirectFieldAccessor(
this.registrar).getPropertyValue("fixedDelayTasks");
- assertThat(tasks.size()).isEqualTo(2);
- assertThat(tasks.get(0).getInterval()).isEqualTo(3000L);
- assertThat(tasks.get(1).getInterval()).isEqualTo(3500L);
- assertThat(tasks.get(1).getInitialDelay()).isEqualTo(250);
+ assertThat(tasks).hasSize(2);
+ assertThat(tasks.get(0).getIntervalDuration()).isEqualTo(Duration.ofMillis(3000L));
+ assertThat(tasks.get(1).getIntervalDuration()).isEqualTo(Duration.ofMillis(3500L));
+ assertThat(tasks.get(1).getInitialDelayDuration()).isEqualTo(Duration.ofMillis(250));
}
@Test
public void cronTasks() {
List tasks = (List) new DirectFieldAccessor(
this.registrar).getPropertyValue("cronTasks");
- assertThat(tasks.size()).isEqualTo(1);
+ assertThat(tasks).hasSize(1);
assertThat(tasks.get(0).getExpression()).isEqualTo("*/4 * 9-17 * * MON-FRI");
}
@@ -107,7 +108,7 @@ public void cronTasks() {
public void triggerTasks() {
List tasks = (List) new DirectFieldAccessor(
this.registrar).getPropertyValue("triggerTasks");
- assertThat(tasks.size()).isEqualTo(1);
+ assertThat(tasks).hasSize(1);
assertThat(tasks.get(0).getTrigger()).isInstanceOf(TestTrigger.class);
}
@@ -122,7 +123,7 @@ public void test() {
static class TestTrigger implements Trigger {
@Override
- public Date nextExecutionTime(TriggerContext triggerContext) {
+ public Instant nextExecution(TriggerContext triggerContext) {
return null;
}
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/support/PeriodicTriggerTests.java b/spring-context/src/test/java/org/springframework/scheduling/support/PeriodicTriggerTests.java
index 60e09f07962b..ba466774a60f 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/support/PeriodicTriggerTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/support/PeriodicTriggerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,11 +16,13 @@
package org.springframework.scheduling.support;
-import java.util.Date;
-import java.util.concurrent.TimeUnit;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import org.junit.jupiter.api.Test;
+import org.springframework.lang.Nullable;
import org.springframework.scheduling.TriggerContext;
import org.springframework.util.NumberUtils;
@@ -34,149 +36,149 @@ public class PeriodicTriggerTests {
@Test
public void fixedDelayFirstExecution() {
- Date now = new Date();
- PeriodicTrigger trigger = new PeriodicTrigger(5000);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant now = Instant.now();
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(5000));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertNegligibleDifference(now, next);
}
@Test
public void fixedDelayWithInitialDelayFirstExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
long initialDelay = 30000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertApproximateDifference(now, next, initialDelay);
}
@Test
public void fixedDelayWithTimeUnitFirstExecution() {
- Date now = new Date();
- PeriodicTrigger trigger = new PeriodicTrigger(5, TimeUnit.SECONDS);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant now = Instant.now();
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(5));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertNegligibleDifference(now, next);
}
@Test
public void fixedDelayWithTimeUnitAndInitialDelayFirstExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5;
long initialDelay = 30;
- PeriodicTrigger trigger = new PeriodicTrigger(period, TimeUnit.SECONDS);
- trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(period));
+ trigger.setInitialDelay(Duration.ofSeconds(initialDelay));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertApproximateDifference(now, next, initialDelay * 1000);
}
@Test
public void fixedDelaySubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, period + 3000);
}
@Test
public void fixedDelayWithInitialDelaySubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
long initialDelay = 30000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, period + 3000);
}
@Test
public void fixedDelayWithTimeUnitSubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5;
- PeriodicTrigger trigger = new PeriodicTrigger(period, TimeUnit.SECONDS);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(period));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, (period * 1000) + 3000);
}
@Test
public void fixedRateFirstExecution() {
- Date now = new Date();
- PeriodicTrigger trigger = new PeriodicTrigger(5000);
+ Instant now = Instant.now();
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(5000));
trigger.setFixedRate(true);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertNegligibleDifference(now, next);
}
@Test
public void fixedRateWithTimeUnitFirstExecution() {
- Date now = new Date();
- PeriodicTrigger trigger = new PeriodicTrigger(5, TimeUnit.SECONDS);
+ Instant now = Instant.now();
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(5));
trigger.setFixedRate(true);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertNegligibleDifference(now, next);
}
@Test
public void fixedRateWithInitialDelayFirstExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
long initialDelay = 30000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
trigger.setFixedRate(true);
trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertApproximateDifference(now, next, initialDelay);
}
@Test
public void fixedRateWithTimeUnitAndInitialDelayFirstExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5;
long initialDelay = 30;
- PeriodicTrigger trigger = new PeriodicTrigger(period, TimeUnit.MINUTES);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMinutes(period));
trigger.setFixedRate(true);
- trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(null, null, null));
+ trigger.setInitialDelay(Duration.ofMinutes(initialDelay));
+ Instant next = trigger.nextExecution(context(null, null, null));
assertApproximateDifference(now, next, (initialDelay * 60 * 1000));
}
@Test
public void fixedRateSubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
trigger.setFixedRate(true);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, period);
}
@Test
public void fixedRateWithInitialDelaySubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5000;
long initialDelay = 30000;
- PeriodicTrigger trigger = new PeriodicTrigger(period);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMillis(period));
trigger.setFixedRate(true);
trigger.setInitialDelay(initialDelay);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, period);
}
@Test
public void fixedRateWithTimeUnitSubsequentExecution() {
- Date now = new Date();
+ Instant now = Instant.now();
long period = 5;
- PeriodicTrigger trigger = new PeriodicTrigger(period, TimeUnit.HOURS);
+ PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofHours(period));
trigger.setFixedRate(true);
- Date next = trigger.nextExecutionTime(context(now, 500, 3000));
+ Instant next = trigger.nextExecution(context(now, 500, 3000));
assertApproximateDifference(now, next, (period * 60 * 60 * 1000));
}
@Test
public void equalsVerification() {
- PeriodicTrigger trigger1 = new PeriodicTrigger(3000);
- PeriodicTrigger trigger2 = new PeriodicTrigger(3000);
+ PeriodicTrigger trigger1 = new PeriodicTrigger(Duration.ofMillis(3000));
+ PeriodicTrigger trigger2 = new PeriodicTrigger(Duration.ofMillis(3000));
assertThat(trigger1.equals(new String("not a trigger"))).isFalse();
assertThat(trigger1.equals(null)).isFalse();
assertThat(trigger1).isEqualTo(trigger1);
@@ -192,44 +194,46 @@ public void equalsVerification() {
assertThat(trigger2.equals(trigger1)).isFalse();
trigger1.setFixedRate(true);
assertThat(trigger2).isEqualTo(trigger1);
- PeriodicTrigger trigger3 = new PeriodicTrigger(3, TimeUnit.SECONDS);
- trigger3.setInitialDelay(7);
+ PeriodicTrigger trigger3 = new PeriodicTrigger(Duration.ofSeconds(3));
+ trigger3.setInitialDelay(Duration.ofSeconds(7));
trigger3.setFixedRate(true);
assertThat(trigger1.equals(trigger3)).isFalse();
assertThat(trigger3.equals(trigger1)).isFalse();
- trigger1.setInitialDelay(7000);
+ trigger1.setInitialDelay(Duration.ofMillis(7000));
assertThat(trigger3).isEqualTo(trigger1);
}
// utility methods
- private static void assertNegligibleDifference(Date d1, Date d2) {
- long diff = Math.abs(d1.getTime() - d2.getTime());
- assertThat(diff < 100).as("difference exceeds threshold: " + diff).isTrue();
+ private static void assertNegligibleDifference(Instant d1, @Nullable Instant d2) {
+ assertThat(Duration.between(d1, d2)).isLessThan(Duration.ofMillis(100));
}
- private static void assertApproximateDifference(Date lesser, Date greater, long expected) {
- long diff = greater.getTime() - lesser.getTime();
+ private static void assertApproximateDifference(Instant lesser, Instant greater, long expected) {
+ long diff = greater.toEpochMilli() - lesser.toEpochMilli();
long variance = Math.abs(expected - diff);
assertThat(variance < 100).as("expected approximate difference of " + expected +
", but actual difference was " + diff).isTrue();
}
- private static TriggerContext context(Object scheduled, Object actual, Object completion) {
- return new TestTriggerContext(asDate(scheduled), asDate(actual), asDate(completion));
+ private static TriggerContext context(@Nullable Object scheduled, @Nullable Object actual,
+ @Nullable Object completion) {
+ return new TestTriggerContext(toInstant(scheduled), toInstant(actual), toInstant(completion));
}
- private static Date asDate(Object o) {
+ @Nullable
+ private static Instant toInstant(@Nullable Object o) {
if (o == null) {
return null;
}
- if (o instanceof Date) {
- return (Date) o;
+ if (o instanceof Instant) {
+ return (Instant) o;
}
if (o instanceof Number) {
- return new Date(System.currentTimeMillis() +
- NumberUtils.convertNumberToTargetClass((Number) o, Long.class));
+ return Instant.now()
+ .plus(NumberUtils.convertNumberToTargetClass((Number) o, Long.class),
+ ChronoUnit.MILLIS);
}
throw new IllegalArgumentException(
"expected Date or Number, but actual type was: " + o.getClass());
@@ -240,30 +244,35 @@ private static Date asDate(Object o) {
private static class TestTriggerContext implements TriggerContext {
- private final Date scheduled;
+ @Nullable
+ private final Instant scheduled;
+
+ @Nullable
+ private final Instant actual;
- private final Date actual;
+ @Nullable
+ private final Instant completion;
- private final Date completion;
+ TestTriggerContext(@Nullable Instant scheduled,
+ @Nullable Instant actual, @Nullable Instant completion) {
- TestTriggerContext(Date scheduled, Date actual, Date completion) {
this.scheduled = scheduled;
this.actual = actual;
this.completion = completion;
}
@Override
- public Date lastActualExecutionTime() {
+ public Instant lastActualExecution() {
return this.actual;
}
@Override
- public Date lastCompletionTime() {
+ public Instant lastCompletion() {
return this.completion;
}
@Override
- public Date lastScheduledExecutionTime() {
+ public Instant lastScheduledExecution() {
return this.scheduled;
}
}
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java
index 7f795eb67e30..c954bc71bace 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandler.java
@@ -17,6 +17,7 @@
package org.springframework.messaging.simp.broker;
import java.security.Principal;
+import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
@@ -254,8 +255,8 @@ public MessageHeaderInitializer getHeaderInitializer() {
public void startInternal() {
publishBrokerAvailableEvent();
if (this.taskScheduler != null) {
- long interval = initHeartbeatTaskDelay();
- if (interval > 0) {
+ Duration interval = initHeartbeatTaskDelay();
+ if (interval.toMillis() > 0) {
this.heartbeatFuture = this.taskScheduler.scheduleWithFixedDelay(new HeartbeatTask(), interval);
}
}
@@ -266,15 +267,15 @@ public void startInternal() {
}
}
- private long initHeartbeatTaskDelay() {
+ private Duration initHeartbeatTaskDelay() {
if (getHeartbeatValue() == null) {
- return 0;
+ return Duration.ZERO;
}
else if (getHeartbeatValue()[0] > 0 && getHeartbeatValue()[1] > 0) {
- return Math.min(getHeartbeatValue()[0], getHeartbeatValue()[1]);
+ return Duration.ofMillis(Math.min(getHeartbeatValue()[0], getHeartbeatValue()[1]));
}
else {
- return (getHeartbeatValue()[0] > 0 ? getHeartbeatValue()[0] : getHeartbeatValue()[1]);
+ return Duration.ofMillis(getHeartbeatValue()[0] > 0 ? getHeartbeatValue()[0] : getHeartbeatValue()[1]);
}
}
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java
index 391325f443d7..576ba7c1a4bf 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/DefaultStompSession.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,9 +17,9 @@
package org.springframework.messaging.simp.stomp;
import java.lang.reflect.Type;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -566,7 +566,7 @@ public ReceiptHandler(@Nullable String receiptId) {
private void initReceiptHandling() {
Assert.notNull(getTaskScheduler(), "To track receipts, a TaskScheduler must be configured");
DefaultStompSession.this.receiptHandlers.put(this.receiptId, this);
- Date startTime = new Date(System.currentTimeMillis() + getReceiptTimeLimit());
+ Instant startTime = Instant.now().plusMillis(getReceiptTimeLimit());
this.future = getTaskScheduler().schedule(this::handleReceiptNotReceived, startTime);
}
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java
index 4a6b1257014b..ec7d60c4428b 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java
@@ -17,6 +17,7 @@
package org.springframework.messaging.simp.stomp;
import java.security.Principal;
+import java.time.Duration;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -457,7 +458,7 @@ protected void startInternal() {
this.tcpClient.connect(handler, new FixedIntervalReconnectStrategy(5000));
if (this.taskScheduler != null) {
- this.taskScheduler.scheduleWithFixedDelay(new ClientSendMessageCountTask(), 5000);
+ this.taskScheduler.scheduleWithFixedDelay(new ClientSendMessageCountTask(), Duration.ofMillis(5000));
}
}
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/UserRegistryMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/UserRegistryMessageHandler.java
index 61d35a174a03..eb55f0110e40 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/UserRegistryMessageHandler.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/UserRegistryMessageHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.messaging.simp.user;
+import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -111,7 +112,7 @@ public long getRegistryExpirationPeriod() {
@Override
public void onApplicationEvent(BrokerAvailabilityEvent event) {
if (event.isBrokerAvailable()) {
- long delay = getRegistryExpirationPeriod() / 2;
+ Duration delay = Duration.ofMillis(getRegistryExpirationPeriod() / 2);
this.scheduledFuture = this.scheduler.scheduleWithFixedDelay(this.schedulerTask, delay);
}
else {
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandlerTests.java
index 72807d3e600e..eba17ef3e7fd 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandlerTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/broker/SimpleBrokerMessageHandlerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,6 +17,7 @@
package org.springframework.messaging.simp.broker;
import java.security.Principal;
+import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
@@ -184,13 +185,13 @@ public void startWithHeartbeatValueWithoutTaskScheduler() {
@SuppressWarnings("rawtypes")
public void startAndStopWithHeartbeatValue() {
ScheduledFuture future = mock(ScheduledFuture.class);
- given(this.taskScheduler.scheduleWithFixedDelay(any(Runnable.class), eq(15000L))).willReturn(future);
+ given(this.taskScheduler.scheduleWithFixedDelay(any(Runnable.class), eq(Duration.ofMillis(15000)))).willReturn(future);
this.messageHandler.setTaskScheduler(this.taskScheduler);
this.messageHandler.setHeartbeatValue(new long[] {15000, 16000});
this.messageHandler.start();
- verify(this.taskScheduler).scheduleWithFixedDelay(any(Runnable.class), eq(15000L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(any(Runnable.class), eq(Duration.ofMillis(15000)));
verifyNoMoreInteractions(this.taskScheduler, future);
this.messageHandler.stop();
@@ -205,7 +206,7 @@ public void startWithOneZeroHeartbeatValue() {
this.messageHandler.setHeartbeatValue(new long[] {0, 10000});
this.messageHandler.start();
- verify(this.taskScheduler).scheduleWithFixedDelay(any(Runnable.class), eq(10000L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(any(Runnable.class), eq(Duration.ofMillis(10000)));
}
@Test
@@ -215,7 +216,7 @@ public void readInactivity() throws Exception {
this.messageHandler.start();
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(1L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(Duration.ofMillis(1)));
Runnable heartbeatTask = taskCaptor.getValue();
assertThat(heartbeatTask).isNotNull();
@@ -246,7 +247,7 @@ public void writeInactivity() throws Exception {
this.messageHandler.start();
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(1L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(Duration.ofMillis(1)));
Runnable heartbeatTask = taskCaptor.getValue();
assertThat(heartbeatTask).isNotNull();
@@ -277,7 +278,7 @@ public void readWriteIntervalCalculation() throws Exception {
this.messageHandler.start();
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(1L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(taskCaptor.capture(), eq(Duration.ofMillis(1)));
Runnable heartbeatTask = taskCaptor.getValue();
assertThat(heartbeatTask).isNotNull();
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/DefaultStompSessionTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/DefaultStompSessionTests.java
index 7f979b54213e..b1c180dc7e6c 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/DefaultStompSessionTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/DefaultStompSessionTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,8 +17,8 @@
package org.springframework.messaging.simp.stomp;
import java.nio.charset.StandardCharsets;
+import java.time.Instant;
import java.util.Arrays;
-import java.util.Date;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicReference;
@@ -628,7 +628,7 @@ public void receiptNotReceived() {
AtomicReference notReceived = new AtomicReference<>();
ScheduledFuture future = mock(ScheduledFuture.class);
- given(taskScheduler.schedule(any(Runnable.class), any(Date.class))).willReturn(future);
+ given(taskScheduler.schedule(any(Runnable.class), any(Instant.class))).willReturn(future);
StompHeaders headers = new StompHeaders();
headers.setDestination("/topic/foo");
@@ -637,7 +637,7 @@ public void receiptNotReceived() {
receiptable.addReceiptLostTask(() -> notReceived.set(true));
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(taskScheduler).schedule(taskCaptor.capture(), (Date) notNull());
+ verify(taskScheduler).schedule(taskCaptor.capture(), (Instant) notNull());
Runnable scheduledTask = taskCaptor.getValue();
assertThat(scheduledTask).isNotNull();
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerTests.java
index 44f52a68b4e5..05e9efe81d6d 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerTests.java
@@ -16,6 +16,7 @@
package org.springframework.messaging.simp.stomp;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -166,7 +167,7 @@ void destinationExcludedWithHeartbeat() {
this.tcpClient.handleMessage(MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders()));
// Run the messageCountTask to clear the message count
- verify(this.brokerRelay.getTaskScheduler()).scheduleWithFixedDelay(this.messageCountTaskCaptor.capture(), eq(5000L));
+ verify(this.brokerRelay.getTaskScheduler()).scheduleWithFixedDelay(this.messageCountTaskCaptor.capture(), eq(Duration.ofMillis(5000L)));
this.messageCountTaskCaptor.getValue().run();
accessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/UserRegistryMessageHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/UserRegistryMessageHandlerTests.java
index e01348ff64d4..60e06786a9ae 100644
--- a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/UserRegistryMessageHandlerTests.java
+++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/UserRegistryMessageHandlerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.messaging.simp.user;
+import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -94,7 +95,7 @@ public void brokerAvailableEvent() throws Exception {
public void brokerUnavailableEvent() throws Exception {
ScheduledFuture future = mock(ScheduledFuture.class);
- given(this.taskScheduler.scheduleWithFixedDelay(any(Runnable.class), any(Long.class))).willReturn(future);
+ given(this.taskScheduler.scheduleWithFixedDelay(any(Runnable.class), any(Duration.class))).willReturn(future);
BrokerAvailabilityEvent event = new BrokerAvailabilityEvent(true, this);
this.handler.onApplicationEvent(event);
@@ -181,7 +182,7 @@ private Runnable getUserRegistryTask() {
this.handler.onApplicationEvent(event);
ArgumentCaptor extends Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
- verify(this.taskScheduler).scheduleWithFixedDelay(captor.capture(), eq(10000L));
+ verify(this.taskScheduler).scheduleWithFixedDelay(captor.capture(), eq(Duration.ofMillis(10000L)));
return captor.getValue();
}
diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/WebSocketStompClient.java b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/WebSocketStompClient.java
index 7c3c7fd045e4..1b65927d016f 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/WebSocketStompClient.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/WebSocketStompClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -403,6 +404,7 @@ private void updateLastWriteTime() {
public void onReadInactivity(final Runnable runnable, final long duration) {
Assert.state(getTaskScheduler() != null, "No TaskScheduler configured");
this.lastReadTime = System.currentTimeMillis();
+ Duration delay = Duration.ofMillis(duration / 2);
this.inactivityTasks.add(getTaskScheduler().scheduleWithFixedDelay(() -> {
if (System.currentTimeMillis() - this.lastReadTime > duration) {
try {
@@ -414,13 +416,14 @@ public void onReadInactivity(final Runnable runnable, final long duration) {
}
}
}
- }, duration / 2));
+ }, delay));
}
@Override
public void onWriteInactivity(final Runnable runnable, final long duration) {
Assert.state(getTaskScheduler() != null, "No TaskScheduler configured");
this.lastWriteTime = System.currentTimeMillis();
+ Duration delay = Duration.ofMillis(duration / 2);
this.inactivityTasks.add(getTaskScheduler().scheduleWithFixedDelay(() -> {
if (System.currentTimeMillis() - this.lastWriteTime > duration) {
try {
@@ -432,7 +435,7 @@ public void onWriteInactivity(final Runnable runnable, final long duration) {
}
}
}
- }, duration / 2));
+ }, delay));
}
@Override
diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequest.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequest.java
index e69f0e2ce60b..fc087e991b98 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequest.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -18,8 +18,9 @@
import java.net.URI;
import java.security.Principal;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -160,7 +161,7 @@ private void scheduleConnectTimeoutTask(ConnectCallback connectHandler) {
if (logger.isTraceEnabled()) {
logger.trace("Scheduling connect to time out after " + this.timeoutValue + " ms.");
}
- Date timeoutDate = new Date(System.currentTimeMillis() + this.timeoutValue);
+ Instant timeoutDate = Instant.now().plus(this.timeoutValue, ChronoUnit.MILLIS);
this.timeoutScheduler.schedule(connectHandler, timeoutDate);
}
else if (logger.isTraceEnabled()) {
diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java
index d456a72a5dd3..1f64138c526c 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2021 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.security.Principal;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -380,6 +381,7 @@ private void scheduleSessionTask() {
if (this.sessionCleanupTask != null) {
return;
}
+ Duration disconnectDelay = Duration.ofMillis(getDisconnectDelay());
this.sessionCleanupTask = getTaskScheduler().scheduleAtFixedRate(() -> {
List removedIds = new ArrayList<>();
for (SockJsSession session : this.sessions.values()) {
@@ -398,7 +400,7 @@ private void scheduleSessionTask() {
if (logger.isDebugEnabled() && !removedIds.isEmpty()) {
logger.debug("Closed " + removedIds.size() + " sessions: " + removedIds);
}
- }, getDisconnectDelay());
+ }, disconnectDelay);
}
}
diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java
index ad334fe9e107..2ea6c1a4fb4d 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/session/AbstractSockJsSession.java
@@ -17,9 +17,10 @@
package org.springframework.web.socket.sockjs.transport.session;
import java.io.IOException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -270,7 +271,7 @@ protected void scheduleHeartbeat() {
if (!isActive()) {
return;
}
- Date time = new Date(System.currentTimeMillis() + this.config.getHeartbeatTime());
+ Instant time = Instant.now().plus(this.config.getHeartbeatTime(), ChronoUnit.MILLIS);
this.heartbeatTask = new HeartbeatTask();
this.heartbeatFuture = this.config.getTaskScheduler().schedule(this.heartbeatTask, time);
if (logger.isTraceEnabled()) {
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/config/HandlersBeanDefinitionParserTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/config/HandlersBeanDefinitionParserTests.java
index 6bf407c83a6e..d146858d978d 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/config/HandlersBeanDefinitionParserTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/config/HandlersBeanDefinitionParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -18,7 +18,8 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Date;
+import java.time.Duration;
+import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
@@ -320,27 +321,27 @@ public ScheduledFuture schedule(Runnable task, Trigger trigger) {
}
@Override
- public ScheduledFuture schedule(Runnable task, Date startTime) {
+ public ScheduledFuture schedule(Runnable task, Instant startTime) {
return null;
}
@Override
- public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
+ public ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period) {
return null;
}
@Override
- public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
+ public ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period) {
return null;
}
@Override
- public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
+ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay) {
return null;
}
@Override
- public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
+ public ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay) {
return null;
}
}
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/messaging/WebSocketStompClientTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/messaging/WebSocketStompClientTests.java
index 4d849bde949c..fba4cf89a7be 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/messaging/WebSocketStompClientTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/messaging/WebSocketStompClientTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -18,6 +18,7 @@
import java.net.URI;
import java.nio.charset.StandardCharsets;
+import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
import org.junit.jupiter.api.BeforeEach;
@@ -295,7 +296,7 @@ public void cancelInactivityTasks() throws Exception {
TcpConnection tcpConnection = getTcpConnection();
ScheduledFuture future = mock(ScheduledFuture.class);
- given(this.taskScheduler.scheduleWithFixedDelay(any(), eq(1L))).willReturn(future);
+ given(this.taskScheduler.scheduleWithFixedDelay(any(), eq(Duration.ofMillis(1)))).willReturn(future);
tcpConnection.onReadInactivity(mock(Runnable.class), 2L);
tcpConnection.onWriteInactivity(mock(Runnable.class), 2L);
@@ -332,7 +333,7 @@ private void testInactivityTaskScheduling(Runnable runnable, long delay, long sl
throws InterruptedException {
ArgumentCaptor inactivityTaskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(this.taskScheduler).scheduleWithFixedDelay(inactivityTaskCaptor.capture(), eq(delay/2));
+ verify(this.taskScheduler).scheduleWithFixedDelay(inactivityTaskCaptor.capture(), eq(Duration.ofMillis(delay/2)));
verifyNoMoreInteractions(this.taskScheduler);
if (sleepTime > 0) {
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequestTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequestTests.java
index b0ce13365383..25bf90e2b7c1 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequestTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/client/DefaultTransportRequestTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -18,7 +18,7 @@
import java.io.IOException;
import java.net.URI;
-import java.util.Date;
+import java.time.Instant;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.BeforeEach;
@@ -115,7 +115,7 @@ public void fallbackAfterTimeout() throws Exception {
// Get and invoke the scheduled timeout task
ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(scheduler).schedule(taskCaptor.capture(), any(Date.class));
+ verify(scheduler).schedule(taskCaptor.capture(), any(Instant.class));
verifyNoMoreInteractions(scheduler);
taskCaptor.getValue().run();
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsServiceTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsServiceTests.java
index 3a651c015b4b..fbd16e581a37 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsServiceTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/DefaultSockJsServiceTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.web.socket.sockjs.transport.handler;
+import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -153,7 +154,7 @@ public void handleTransportRequestXhr() throws Exception {
assertThat(this.servletResponse.getStatus()).isEqualTo(200);
verify(this.xhrHandler).handleRequest(this.request, this.response, this.wsHandler, this.session);
- verify(taskScheduler).scheduleAtFixedRate(any(Runnable.class), eq(service.getDisconnectDelay()));
+ verify(taskScheduler).scheduleAtFixedRate(any(Runnable.class), eq(Duration.ofMillis(this.service.getDisconnectDelay())));
assertThat(this.response.getHeaders().getCacheControl()).isEqualTo("no-store, no-cache, must-revalidate, max-age=0");
assertThat(this.servletResponse.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isNull();
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/HttpSendingTransportHandlerTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/HttpSendingTransportHandlerTests.java
index 48cb9bd4392e..4eafd96a4cc5 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/HttpSendingTransportHandlerTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/handler/HttpSendingTransportHandlerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -16,7 +16,7 @@
package org.springframework.web.socket.sockjs.transport.handler;
-import java.util.Date;
+import java.time.Instant;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -81,7 +81,7 @@ public void handleRequestXhr() throws Exception {
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertThat(this.servletRequest.isAsyncStarted()).as("Polling request should remain open").isTrue();
- verify(this.taskScheduler).schedule(any(Runnable.class), any(Date.class));
+ verify(this.taskScheduler).schedule(any(Runnable.class), any(Instant.class));
resetRequestAndResponse();
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java
index 2421ded37e43..649568878df6 100644
--- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java
+++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/transport/session/SockJsSessionTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -17,8 +17,8 @@
package org.springframework.web.socket.sockjs.transport.session;
import java.io.IOException;
+import java.time.Instant;
import java.util.Collections;
-import java.util.Date;
import java.util.concurrent.ScheduledFuture;
import org.junit.jupiter.api.Test;
@@ -262,7 +262,7 @@ public void sendHeartbeat() {
assertThat(this.session.getSockJsFramesWritten().size()).isEqualTo(1);
assertThat(this.session.getSockJsFramesWritten().get(0)).isEqualTo(SockJsFrame.heartbeatFrame());
- verify(this.taskScheduler).schedule(any(Runnable.class), any(Date.class));
+ verify(this.taskScheduler).schedule(any(Runnable.class), any(Instant.class));
verifyNoMoreInteractions(this.taskScheduler);
}
@@ -286,12 +286,12 @@ public void sendHeartbeatWhenDisabled() {
@Test
public void scheduleAndCancelHeartbeat() {
ScheduledFuture> task = mock(ScheduledFuture.class);
- willReturn(task).given(this.taskScheduler).schedule(any(Runnable.class), any(Date.class));
+ willReturn(task).given(this.taskScheduler).schedule(any(Runnable.class), any(Instant.class));
this.session.setActive(true);
this.session.scheduleHeartbeat();
- verify(this.taskScheduler).schedule(any(Runnable.class), any(Date.class));
+ verify(this.taskScheduler).schedule(any(Runnable.class), any(Instant.class));
verifyNoMoreInteractions(this.taskScheduler);
given(task.isCancelled()).willReturn(false);
diff --git a/src/docs/asciidoc/integration.adoc b/src/docs/asciidoc/integration.adoc
index 947a734f94c1..b8f0da9eb1f4 100644
--- a/src/docs/asciidoc/integration.adoc
+++ b/src/docs/asciidoc/integration.adoc
@@ -3836,27 +3836,17 @@ The following listing shows the `TaskScheduler` interface definition:
ScheduledFuture schedule(Runnable task, Instant startTime);
- ScheduledFuture schedule(Runnable task, Date startTime);
-
ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
- ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
-
ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period);
- ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
-
ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
- ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
-
ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay);
- ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
- }
----
-The simplest method is the one named `schedule` that takes only a `Runnable` and a `Date`.
+The simplest method is the one named `schedule` that takes only a `Runnable` and an `Instant`.
That causes the task to run once after the specified time. All of the other methods
are capable of scheduling tasks to run repeatedly. The fixed-rate and fixed-delay
methods are for simple, periodic execution, but the method that accepts a `Trigger` is