Browse Source

Fix custom scheduler support for @Scheduled methods

This commit fixes a regression introduced by gh-24560, when adding
execution metadata support for scheduled tasks. The
`OutcomeTrackingRunnable` would delegate to the actual runnable but
could also hide whether it implements the `SchedulingAwareRunnable`
contract.

This commit ensures that `OutcomeTrackingRunnable` always implements
that contract and delegates to the runnable if possible, or return
default values otherwise.

Fixes gh-34058
pull/34398/head
Brian Clozel 1 year ago
parent
commit
0c688742e1
  1. 21
      spring-context/src/main/java/org/springframework/scheduling/config/Task.java
  2. 16
      spring-context/src/test/java/org/springframework/scheduling/config/TaskTests.java

21
spring-context/src/main/java/org/springframework/scheduling/config/Task.java

@ -18,6 +18,8 @@ package org.springframework.scheduling.config;
import java.time.Instant; import java.time.Instant;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -68,7 +70,7 @@ public class Task {
} }
private class OutcomeTrackingRunnable implements Runnable { private class OutcomeTrackingRunnable implements SchedulingAwareRunnable {
private final Runnable runnable; private final Runnable runnable;
@ -89,6 +91,23 @@ public class Task {
} }
} }
@Override
public boolean isLongLived() {
if (this.runnable instanceof SchedulingAwareRunnable sar) {
return sar.isLongLived();
}
return SchedulingAwareRunnable.super.isLongLived();
}
@Nullable
@Override
public String getQualifier() {
if (this.runnable instanceof SchedulingAwareRunnable sar) {
return sar.getQualifier();
}
return SchedulingAwareRunnable.super.getQualifier();
}
@Override @Override
public String toString() { public String toString() {
return this.runnable.toString(); return this.runnable.toString();

16
spring-context/src/test/java/org/springframework/scheduling/config/TaskTests.java

@ -16,8 +16,12 @@
package org.springframework.scheduling.config; package org.springframework.scheduling.config;
import io.micrometer.observation.tck.TestObservationRegistry;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.scheduling.support.ScheduledMethodRunnable;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
@ -72,6 +76,18 @@ class TaskTests {
assertThat(executionOutcome.throwable()).isInstanceOf(IllegalStateException.class); assertThat(executionOutcome.throwable()).isInstanceOf(IllegalStateException.class);
} }
@Test
void shouldDelegateToSchedulingAwareRunnable() throws Exception {
ScheduledMethodRunnable methodRunnable = new ScheduledMethodRunnable(new TestRunnable(),
TestRunnable.class.getMethod("run"), "myScheduler", TestObservationRegistry::create);
Task task = new Task(methodRunnable);
assertThat(task.getRunnable()).isInstanceOf(SchedulingAwareRunnable.class);
SchedulingAwareRunnable actual = (SchedulingAwareRunnable) task.getRunnable();
assertThat(actual.getQualifier()).isEqualTo(methodRunnable.getQualifier());
assertThat(actual.isLongLived()).isEqualTo(methodRunnable.isLongLived());
}
static class TestRunnable implements Runnable { static class TestRunnable implements Runnable {

Loading…
Cancel
Save