|
|
|
@ -19,7 +19,7 @@ package org.springframework.scheduling.annotation;
@@ -19,7 +19,7 @@ package org.springframework.scheduling.annotation;
|
|
|
|
|
import java.util.Date; |
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
|
|
|
|
|
|
import org.junit.Ignore; |
|
|
|
|
import org.junit.After; |
|
|
|
|
import org.junit.Rule; |
|
|
|
|
import org.junit.Test; |
|
|
|
|
import org.junit.rules.ExpectedException; |
|
|
|
@ -36,12 +36,8 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
@@ -36,12 +36,8 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
|
|
|
|
import org.springframework.tests.Assume; |
|
|
|
|
import org.springframework.tests.TestGroup; |
|
|
|
|
|
|
|
|
|
import static org.hamcrest.Matchers.both; |
|
|
|
|
import static org.hamcrest.Matchers.greaterThan; |
|
|
|
|
import static org.hamcrest.Matchers.greaterThanOrEqualTo; |
|
|
|
|
import static org.hamcrest.Matchers.lessThanOrEqualTo; |
|
|
|
|
import static org.hamcrest.Matchers.startsWith; |
|
|
|
|
import static org.junit.Assert.assertThat; |
|
|
|
|
import static org.hamcrest.Matchers.*; |
|
|
|
|
import static org.junit.Assert.*; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Tests use of @EnableScheduling on @Configuration classes. |
|
|
|
@ -55,62 +51,151 @@ public class EnableSchedulingTests {
@@ -55,62 +51,151 @@ public class EnableSchedulingTests {
|
|
|
|
|
@Rule |
|
|
|
|
public final ExpectedException exception = ExpectedException.none(); |
|
|
|
|
|
|
|
|
|
private AnnotationConfigApplicationContext ctx; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@After |
|
|
|
|
public void tearDown() { |
|
|
|
|
if (ctx != null) { |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withFixedRateTask() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfig.class); |
|
|
|
|
ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withSubclass() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class FixedRateTaskConfig { |
|
|
|
|
ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfigSubclass.class); |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
public AtomicInteger counter() { |
|
|
|
|
return new AtomicInteger(); |
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Scheduled(fixedRate = 10) |
|
|
|
|
public void task() { |
|
|
|
|
counter().incrementAndGet(); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
public void withExplicitScheduler() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(ExplicitSchedulerConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
assertThat(ctx.getBean(ExplicitSchedulerConfig.class).threadName, startsWith("explicitScheduler-")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withExplicitSchedulerAmbiguity_andSchedulingEnabled() { |
|
|
|
|
// No exception raised as of 4.3, aligned with the behavior for @Async methods (SPR-14030)
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(AmbiguousExplicitSchedulerConfig.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withSubclass() throws InterruptedException { |
|
|
|
|
public void withExplicitScheduledTaskRegistrar() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfigSubclass.class); |
|
|
|
|
ctx = new AnnotationConfigApplicationContext(ExplicitScheduledTaskRegistrarConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
ctx.close(); |
|
|
|
|
assertThat(ctx.getBean(ExplicitScheduledTaskRegistrarConfig.class).threadName, startsWith("explicitScheduler1")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_butNoActualTasks() { |
|
|
|
|
ctx = new AnnotationConfigApplicationContext(SchedulingEnabled_withAmbiguousTaskSchedulers_butNoActualTasks.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
static class FixedRateTaskConfigSubclass extends FixedRateTaskConfig { |
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask() { |
|
|
|
|
// No exception raised as of 4.3, aligned with the behavior for @Async methods (SPR-14030)
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrarBean() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrar.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("explicitScheduler2-")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withExplicitScheduler() throws InterruptedException { |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ExplicitSchedulerConfig.class); |
|
|
|
|
ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
assertThat(ctx.getBean(ExplicitSchedulerConfig.class).threadName, startsWith("explicitScheduler-")); |
|
|
|
|
ctx.close(); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("explicitScheduler2-")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withTaskAddedVia_configureTasks() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(SchedulingEnabled_withTaskAddedVia_configureTasks.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("taskScheduler-")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withTriggerTask() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(TriggerTaskConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThan(1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withInitiallyDelayedFixedRateTask() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfig_withInitialDelay.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(1950); |
|
|
|
|
AtomicInteger counter = ctx.getBean(AtomicInteger.class); |
|
|
|
|
|
|
|
|
|
// The @Scheduled method should have been called at least once but
|
|
|
|
|
// not more times than the delay allows.
|
|
|
|
|
assertThat(counter.get(), both(greaterThan(0)).and(lessThanOrEqualTo(10))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class FixedRateTaskConfig { |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
public AtomicInteger counter() { |
|
|
|
|
return new AtomicInteger(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Scheduled(fixedRate = 10) |
|
|
|
|
public void task() { |
|
|
|
|
counter().incrementAndGet(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
static class FixedRateTaskConfigSubclass extends FixedRateTaskConfig { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -140,16 +225,6 @@ public class EnableSchedulingTests {
@@ -140,16 +225,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Ignore("Disabled until SPR-14030 is resolved") |
|
|
|
|
@Test |
|
|
|
|
@SuppressWarnings("resource") |
|
|
|
|
public void withExplicitSchedulerAmbiguity_andSchedulingEnabled() { |
|
|
|
|
exception.expect(IllegalStateException.class); |
|
|
|
|
exception.expectMessage(startsWith("More than one TaskScheduler bean exists within the context")); |
|
|
|
|
new AnnotationConfigApplicationContext(AmbiguousExplicitSchedulerConfig.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class AmbiguousExplicitSchedulerConfig { |
|
|
|
@ -174,20 +249,6 @@ public class EnableSchedulingTests {
@@ -174,20 +249,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withExplicitScheduledTaskRegistrar() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
ExplicitScheduledTaskRegistrarConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThanOrEqualTo(10)); |
|
|
|
|
assertThat(ctx.getBean(ExplicitScheduledTaskRegistrarConfig.class).threadName, startsWith("explicitScheduler1")); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class ExplicitScheduledTaskRegistrarConfig implements SchedulingConfigurer { |
|
|
|
@ -230,14 +291,6 @@ public class EnableSchedulingTests {
@@ -230,14 +291,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_butNoActualTasks() { |
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withAmbiguousTaskSchedulers_butNoActualTasks.class); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class SchedulingEnabled_withAmbiguousTaskSchedulers_butNoActualTasks { |
|
|
|
@ -258,16 +311,6 @@ public class EnableSchedulingTests {
@@ -258,16 +311,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Ignore("Disabled until SPR-14030 is resolved") |
|
|
|
|
@Test |
|
|
|
|
@SuppressWarnings("resource") |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask() { |
|
|
|
|
exception.expect(IllegalStateException.class); |
|
|
|
|
exception.expectMessage(startsWith("More than one TaskScheduler bean exists within the context")); |
|
|
|
|
new AnnotationConfigApplicationContext(SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask { |
|
|
|
@ -292,19 +335,6 @@ public class EnableSchedulingTests {
@@ -292,19 +335,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrarBean() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrar.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(20); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("explicitScheduler2-")); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static class ThreadAwareWorker { |
|
|
|
|
|
|
|
|
|
String executedByThread; |
|
|
|
@ -346,19 +376,6 @@ public class EnableSchedulingTests {
@@ -346,19 +376,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(20); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("explicitScheduler2-")); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute implements SchedulingConfigurer { |
|
|
|
@ -394,19 +411,6 @@ public class EnableSchedulingTests {
@@ -394,19 +411,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withTaskAddedVia_configureTasks() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
SchedulingEnabled_withTaskAddedVia_configureTasks.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(20); |
|
|
|
|
assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread, startsWith("taskScheduler-")); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class SchedulingEnabled_withTaskAddedVia_configureTasks implements SchedulingConfigurer { |
|
|
|
@ -436,18 +440,6 @@ public class EnableSchedulingTests {
@@ -436,18 +440,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withTriggerTask() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TriggerTaskConfig.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
assertThat(ctx.getBean(AtomicInteger.class).get(), greaterThan(1)); |
|
|
|
|
ctx.close(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
static class TriggerTaskConfig { |
|
|
|
|
|
|
|
|
@ -478,23 +470,6 @@ public class EnableSchedulingTests {
@@ -478,23 +470,6 @@ public class EnableSchedulingTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void withInitiallyDelayedFixedRateTask() throws InterruptedException { |
|
|
|
|
Assume.group(TestGroup.PERFORMANCE); |
|
|
|
|
|
|
|
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext( |
|
|
|
|
FixedRateTaskConfig_withInitialDelay.class); |
|
|
|
|
|
|
|
|
|
Thread.sleep(1950); |
|
|
|
|
AtomicInteger counter = ctx.getBean(AtomicInteger.class); |
|
|
|
|
ctx.close(); |
|
|
|
|
|
|
|
|
|
// The @Scheduled method should have been called at least once but
|
|
|
|
|
// not more times than the delay allows.
|
|
|
|
|
assertThat(counter.get(), both(greaterThan(0)).and(lessThanOrEqualTo(10))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
@EnableScheduling |
|
|
|
|
static class FixedRateTaskConfig_withInitialDelay { |
|
|
|
|