From fa72f90a106fa67fc5df74b7336646467f4c9701 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 30 Jun 2023 08:47:34 +0100 Subject: [PATCH] Avoid NPE when a PeriodicTrigger has no initial delay Closes gh-36081 --- .../scheduling/ScheduledTasksEndpoint.java | 4 +- .../ScheduledTasksEndpointTests.java | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java index bdfd42bb433..7b666c8b05c 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.scheduling; import java.lang.reflect.Method; +import java.time.Duration; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; @@ -186,7 +187,8 @@ public class ScheduledTasksEndpoint { protected IntervalTaskDescriptor(TaskType type, TriggerTask task, PeriodicTrigger trigger) { super(type, task.getRunnable()); - this.initialDelay = trigger.getInitialDelayDuration().toMillis(); + Duration initialDelayDuration = trigger.getInitialDelayDuration(); + this.initialDelay = (initialDelayDuration != null) ? initialDelayDuration.toMillis() : 0; this.interval = trigger.getPeriodDuration().toMillis(); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpointTests.java index 0e5a3623ab9..8befd959fcd 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpointTests.java @@ -113,6 +113,20 @@ class ScheduledTasksEndpointTests { }); } + @Test + void noInitialDelayFixedDelayTriggerIsReported() { + run(NoInitialDelayFixedDelayTriggerTask.class, (tasks) -> { + assertThat(tasks.getCron()).isEmpty(); + assertThat(tasks.getFixedRate()).isEmpty(); + assertThat(tasks.getCustom()).isEmpty(); + assertThat(tasks.getFixedDelay()).hasSize(1); + FixedDelayTaskDescriptor description = (FixedDelayTaskDescriptor) tasks.getFixedDelay().get(0); + assertThat(description.getInitialDelay()).isEqualTo(0); + assertThat(description.getInterval()).isEqualTo(1000); + assertThat(description.getRunnable().getTarget()).isEqualTo(FixedDelayTriggerRunnable.class.getName()); + }); + } + @Test void fixedRateScheduledMethodIsReported() { run(FixedRateScheduledMethod.class, (tasks) -> { @@ -142,6 +156,20 @@ class ScheduledTasksEndpointTests { }); } + @Test + void noInitialDelayFixedRateTriggerIsReported() { + run(NoInitialDelayFixedRateTriggerTask.class, (tasks) -> { + assertThat(tasks.getCron()).isEmpty(); + assertThat(tasks.getFixedDelay()).isEmpty(); + assertThat(tasks.getCustom()).isEmpty(); + assertThat(tasks.getFixedRate()).hasSize(1); + FixedRateTaskDescriptor description = (FixedRateTaskDescriptor) tasks.getFixedRate().get(0); + assertThat(description.getInitialDelay()).isEqualTo(0); + assertThat(description.getInterval()).isEqualTo(2000); + assertThat(description.getRunnable().getTarget()).isEqualTo(FixedRateTriggerRunnable.class.getName()); + }); + } + @Test void taskWithCustomTriggerIsReported() { run(CustomTriggerTask.class, (tasks) -> { @@ -223,6 +251,16 @@ class ScheduledTasksEndpointTests { } + static class NoInitialDelayFixedDelayTriggerTask implements SchedulingConfigurer { + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(1)); + taskRegistrar.addTriggerTask(new FixedDelayTriggerRunnable(), trigger); + } + + } + static class FixedRateTriggerTask implements SchedulingConfigurer { @Override @@ -235,6 +273,17 @@ class ScheduledTasksEndpointTests { } + static class NoInitialDelayFixedRateTriggerTask implements SchedulingConfigurer { + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofSeconds(2)); + trigger.setFixedRate(true); + taskRegistrar.addTriggerTask(new FixedRateTriggerRunnable(), trigger); + } + + } + static class CronTriggerTask implements SchedulingConfigurer { @Override