From b28d96af7de438aa32f1a2c2e22c15cb91009f08 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 14 Apr 2016 21:59:02 +0200 Subject: [PATCH] ScheduledAnnotationBeanPostProcessor accepts non-void methods as well Issue: SPR-14175 --- .../ScheduledAnnotationBeanPostProcessor.java | 2 - ...duledAnnotationBeanPostProcessorTests.java | 93 +++++++++++-------- 2 files changed, 56 insertions(+), 39 deletions(-) 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 7089ee15ac..153e179723 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 @@ -287,8 +287,6 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, protected void processScheduled(Scheduled scheduled, Method method, Object bean) { try { - Assert.isTrue(void.class == method.getReturnType(), - "Only void-returning methods may be annotated with @Scheduled"); Assert.isTrue(method.getParameterTypes().length == 0, "Only no-arg methods may be annotated with @Scheduled"); 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 4318911197..6f5a00b20a 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 @@ -539,6 +539,31 @@ public class ScheduledAnnotationBeanPostProcessorTests { assertEquals(businessHoursCronExpression, task.getExpression()); } + @Test + public void nonVoidReturnType() { + BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); + BeanDefinition targetDefinition = new RootBeanDefinition(NonVoidReturnTypeTestBean.class); + context.registerBeanDefinition("postProcessor", processorDefinition); + context.registerBeanDefinition("target", targetDefinition); + context.refresh(); + + Object postProcessor = context.getBean("postProcessor"); + Object target = context.getBean("target"); + ScheduledTaskRegistrar registrar = (ScheduledTaskRegistrar) + new DirectFieldAccessor(postProcessor).getPropertyValue("registrar"); + @SuppressWarnings("unchecked") + List cronTasks = (List) + new DirectFieldAccessor(registrar).getPropertyValue("cronTasks"); + assertEquals(1, cronTasks.size()); + CronTask task = cronTasks.get(0); + ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable(); + Object targetObject = runnable.getTarget(); + Method targetMethod = runnable.getMethod(); + assertEquals(target, targetObject); + assertEquals("cron", targetMethod.getName()); + assertEquals("0 0 9-17 * * MON-FRI", task.getExpression()); + } + @Test(expected = BeanCreationException.class) public void emptyAnnotation() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); @@ -557,15 +582,6 @@ public class ScheduledAnnotationBeanPostProcessorTests { context.refresh(); } - @Test(expected = BeanCreationException.class) - public void nonVoidReturnType() { - BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); - BeanDefinition targetDefinition = new RootBeanDefinition(NonVoidReturnTypeTestBean.class); - context.registerBeanDefinition("postProcessor", processorDefinition); - context.registerBeanDefinition("target", targetDefinition); - context.refresh(); - } - @Test(expected = BeanCreationException.class) public void nonEmptyParamList() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); @@ -578,7 +594,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class FixedDelayTestBean { - @Scheduled(fixedDelay=5000) + @Scheduled(fixedDelay = 5000) public void fixedDelay() { } } @@ -586,7 +602,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class FixedRateTestBean { - @Scheduled(fixedRate=3000) + @Scheduled(fixedRate = 3000) public void fixedRate() { } } @@ -594,7 +610,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class FixedRateWithInitialDelayTestBean { - @Scheduled(fixedRate=3000, initialDelay=1000) + @Scheduled(fixedRate = 3000, initialDelay = 1000) public void fixedRate() { } } @@ -611,8 +627,8 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class SeveralFixedRatesWithRepeatedScheduledAnnotationTestBean { - @Scheduled(fixedRate=4000) - @Scheduled(fixedRate=4000, initialDelay=2000) + @Scheduled(fixedRate = 4000) + @Scheduled(fixedRate = 4000, initialDelay = 2000) public void fixedRate() { } } @@ -620,8 +636,8 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class FixedRatesBaseBean { - @Scheduled(fixedRate=4000) - @Scheduled(fixedRate=4000, initialDelay=2000) + @Scheduled(fixedRate = 4000) + @Scheduled(fixedRate = 4000, initialDelay = 2000) public void fixedRate() { } } @@ -633,8 +649,8 @@ public class ScheduledAnnotationBeanPostProcessorTests { interface FixedRatesDefaultMethod { - @Scheduled(fixedRate=4000) - @Scheduled(fixedRate=4000, initialDelay=2000) + @Scheduled(fixedRate = 4000) + @Scheduled(fixedRate = 4000, initialDelay = 2000) default void fixedRate() { } } @@ -647,7 +663,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { @Validated static class CronTestBean { - @Scheduled(cron="*/7 * * * * ?") + @Scheduled(cron = "*/7 * * * * ?") private void cron() throws IOException { throw new IOException("no no no"); } @@ -656,7 +672,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class CronWithTimezoneTestBean { - @Scheduled(cron="0 0 0-4,6-23 * * ?", zone = "GMT+10") + @Scheduled(cron = "0 0 0-4,6-23 * * ?", zone = "GMT+10") protected void cron() throws IOException { throw new IOException("no no no"); } @@ -665,13 +681,22 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class CronWithInvalidTimezoneTestBean { - @Scheduled(cron="0 0 0-4,6-23 * * ?", zone = "FOO") + @Scheduled(cron = "0 0 0-4,6-23 * * ?", zone = "FOO") public void cron() throws IOException { throw new IOException("no no no"); } } + static class NonVoidReturnTypeTestBean { + + @Scheduled(cron = "0 0 9-17 * * MON-FRI") + public String cron() { + return "oops"; + } + } + + static class EmptyAnnotationTestBean { @Scheduled @@ -682,36 +707,27 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class InvalidCronTestBean { - @Scheduled(cron="abc") + @Scheduled(cron = "abc") public void invalid() { } } - static class NonVoidReturnTypeTestBean { - - @Scheduled(fixedRate=3000) - public String invalid() { - return "oops"; - } - } - - static class NonEmptyParamListTestBean { - @Scheduled(fixedRate=3000) + @Scheduled(fixedRate = 3000) public void invalid(String oops) { } } - @Scheduled(fixedRate=5000) + @Scheduled(fixedRate = 5000) @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) private @interface EveryFiveSeconds { } - @Scheduled(cron="0 0 * * * ?") + @Scheduled(cron = "0 0 * * * ?") @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) private @interface Hourly { @@ -728,6 +744,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { long fixedRate() default -1; } + static class MetaAnnotationFixedRateTestBean { @EveryFiveSeconds @@ -735,6 +752,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { } } + static class ComposedAnnotationFixedRateTestBean { @WaitASec(fixedRate = 5000) @@ -742,6 +760,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { } } + static class MetaAnnotationCronTestBean { @Hourly @@ -759,7 +778,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class PropertyPlaceholderWithFixedDelayTestBean { - @Scheduled(fixedDelayString="${fixedDelay}", initialDelayString="${initialDelay}") + @Scheduled(fixedDelayString = "${fixedDelay}", initialDelayString = "${initialDelay}") public void fixedDelay() { } } @@ -767,7 +786,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { static class PropertyPlaceholderWithFixedRateTestBean { - @Scheduled(fixedRateString="${fixedRate}", initialDelayString="${initialDelay}") + @Scheduled(fixedRateString = "${fixedRate}", initialDelayString = "${initialDelay}") public void fixedRate() { } } @@ -781,7 +800,7 @@ public class ScheduledAnnotationBeanPostProcessorTests { } - @Scheduled(cron="${schedules.businessHours}") + @Scheduled(cron = "${schedules.businessHours}") @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) private @interface BusinessHours {