Skip to content

Commit 4d5fe57

Browse files
committed
Polish scheduled task execution infrastructure
In anticipation of substantive changes required to implement "initial delay" support in the <task:scheduled> element and @scheduled annotation, the following updates have been made to the components and infrastructure supporting scheduled task execution: - Fix code style violations - Fix compiler warnings - Add Javadoc where missing, update to use {@code} tags, etc. - Organize imports to follow conventions
1 parent e2fbaa8 commit 4d5fe57

File tree

9 files changed

+109
-84
lines changed

9 files changed

+109
-84
lines changed

spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,11 +24,11 @@
2424

2525
/**
2626
* Annotation that marks a method to be scheduled. Exactly one of the
27-
* <code>cron</code>, <code>fixedDelay</code>, or <code>fixedRate</code>
28-
* attributes must be provided.
27+
* {@link #cron()}, {@link #fixedDelay()}, or {@link #fixedRate()}
28+
* attributes must be specified.
2929
*
3030
* <p>The annotated method must expect no arguments and have a
31-
* <code>void</code> return type.
31+
* {@code void} return type.
3232
*
3333
* <p>Processing of {@code @Scheduled} annotations is performed by
3434
* registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
@@ -49,9 +49,10 @@
4949
/**
5050
* A cron-like expression, extending the usual UN*X definition to include
5151
* triggers on the second as well as minute, hour, day of month, month
52-
* and day of week. e.g. <code>"0 * * * * MON-FRI"</code> means once
53-
* per minute on weekdays (at the top of the minute - the 0th second).
52+
* and day of week. e.g. {@code "0 * * * * MON-FRI"} means once per minute on
53+
* weekdays (at the top of the minute - the 0th second).
5454
* @return an expression that can be parsed to a cron schedule
55+
* @see org.springframework.scheduling.support.CronSequenceGenerator
5556
*/
5657
String cron() default "";
5758

spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package org.springframework.scheduling.annotation;
1818

1919
import java.lang.reflect.Method;
20+
2021
import java.util.HashMap;
2122
import java.util.Map;
2223
import java.util.concurrent.ScheduledExecutorService;
@@ -104,7 +105,6 @@ public int getOrder() {
104105
return LOWEST_PRECEDENCE;
105106
}
106107

107-
108108
public Object postProcessBeforeInitialization(Object bean, String beanName) {
109109
return bean;
110110
}
@@ -124,9 +124,11 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
124124
// found a @Scheduled method on the target class for this JDK proxy -> is it
125125
// also present on the proxy itself?
126126
method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
127-
} catch (SecurityException ex) {
127+
}
128+
catch (SecurityException ex) {
128129
ReflectionUtils.handleReflectionException(ex);
129-
} catch (NoSuchMethodException ex) {
130+
}
131+
catch (NoSuchMethodException ex) {
130132
throw new IllegalStateException(String.format(
131133
"@Scheduled method '%s' found on bean target class '%s', " +
132134
"but not found in any interface(s) for bean JDK proxy. Either " +
@@ -137,7 +139,7 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
137139
}
138140
Runnable runnable = new ScheduledMethodRunnable(bean, method);
139141
boolean processedSchedule = false;
140-
String errorMessage = "Exactly one of 'cron', 'fixedDelay', or 'fixedRate' is required.";
142+
String errorMessage = "Exactly one of the 'cron', 'fixedDelay', or 'fixedRate' attributes is required.";
141143
String cron = annotation.cron();
142144
if (!"".equals(cron)) {
143145
processedSchedule = true;
@@ -170,7 +172,8 @@ public void onApplicationEvent(ContextRefreshedEvent event) {
170172
return;
171173
}
172174

173-
Map<String, SchedulingConfigurer> configurers = applicationContext.getBeansOfType(SchedulingConfigurer.class);
175+
Map<String, SchedulingConfigurer> configurers =
176+
this.applicationContext.getBeansOfType(SchedulingConfigurer.class);
174177

175178
if (this.cronTasks.isEmpty() && this.fixedDelayTasks.isEmpty() &&
176179
this.fixedRateTasks.isEmpty() && configurers.isEmpty()) {
@@ -190,19 +193,23 @@ public void onApplicationEvent(ContextRefreshedEvent event) {
190193
configurer.configureTasks(this.registrar);
191194
}
192195

193-
if (registrar.getScheduler() == null) {
196+
if (this.registrar.getScheduler() == null) {
194197
Map<String, ? super Object> schedulers = new HashMap<String, Object>();
195198
schedulers.putAll(applicationContext.getBeansOfType(TaskScheduler.class));
196199
schedulers.putAll(applicationContext.getBeansOfType(ScheduledExecutorService.class));
197200
if (schedulers.size() == 0) {
198201
// do nothing -> fall back to default scheduler
199-
} else if (schedulers.size() == 1) {
202+
}
203+
else if (schedulers.size() == 1) {
200204
this.registrar.setScheduler(schedulers.values().iterator().next());
201-
} else if (schedulers.size() >= 2){
202-
throw new IllegalStateException("More than one TaskScheduler and/or ScheduledExecutorService " +
203-
"exist within the context. Remove all but one of the beans; or implement the " +
204-
"SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler " +
205-
"explicitly within the configureTasks() callback. Found the following beans: " + schedulers.keySet());
205+
}
206+
else if (schedulers.size() >= 2){
207+
throw new IllegalStateException(
208+
"More than one TaskScheduler and/or ScheduledExecutorService " +
209+
"exist within the context. Remove all but one of the beans; or " +
210+
"implement the SchedulingConfigurer interface and call " +
211+
"ScheduledTaskRegistrar#setScheduler explicitly within the " +
212+
"configureTasks() callback. Found the following beans: " + schedulers.keySet());
206213
}
207214
}
208215

spring-context/src/main/java/org/springframework/scheduling/annotation/SchedulingConfigurer.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,12 +19,15 @@
1919
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
2020

2121
/**
22-
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration}
23-
* classes annotated with @{@link EnableScheduling} that wish to register scheduled tasks
24-
* in a <em>programmatic</em> fashion as opposed to the <em>declarative</em> approach of
25-
* using the @{@link Scheduled} annotation. For example, this may be necessary when
26-
* implementing {@link org.springframework.scheduling.Trigger Trigger}-based tasks, which
27-
* are not supported by the {@code @Scheduled} annotation.
22+
* Optional interface to be implemented by @{@link
23+
* org.springframework.context.annotation.Configuration Configuration} classes annotated
24+
* with @{@link EnableScheduling}. Typically used for setting a specific
25+
* {@link org.springframework.scheduling.TaskScheduler TaskScheduler} bean to be used when
26+
* executing scheduled tasks or for registering scheduled tasks in a <em>programmatic</em>
27+
* fashion as opposed to the <em>declarative</em> approach of using the @{@link Scheduled}
28+
* annotation. For example, this may be necessary when implementing {@link
29+
* org.springframework.scheduling.Trigger Trigger}-based tasks, which are not supported by
30+
* the {@code @Scheduled} annotation.
2831
*
2932
* <p>See @{@link EnableScheduling} for detailed usage examples.
3033
*

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

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -65,17 +65,17 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
6565

6666

6767
/**
68-
* Set the TaskScheduler to register scheduled tasks with.
68+
* Set the {@link TaskScheduler} to register scheduled tasks with.
6969
*/
7070
public void setTaskScheduler(TaskScheduler taskScheduler) {
7171
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
7272
this.taskScheduler = taskScheduler;
7373
}
7474

7575
/**
76-
* Set the {@link org.springframework.scheduling.TaskScheduler} to register scheduled
77-
* tasks with, or a {@link java.util.concurrent.ScheduledExecutorService} to be
78-
* wrapped as a TaskScheduler.
76+
* Set the {@link TaskScheduler} to register scheduled tasks with, or a
77+
* {@link java.util.concurrent.ScheduledExecutorService} to be wrapped as a
78+
* {@code TaskScheduler}.
7979
*/
8080
public void setScheduler(Object scheduler) {
8181
Assert.notNull(scheduler, "Scheduler object must not be null");
@@ -91,7 +91,7 @@ else if (scheduler instanceof ScheduledExecutorService) {
9191
}
9292

9393
/**
94-
* Return the scheduler instance for this registrar (may be null)
94+
* Return the {@link TaskScheduler} instance for this registrar (may be {@code null}).
9595
*/
9696
public TaskScheduler getScheduler() {
9797
return this.taskScheduler;
@@ -121,6 +121,14 @@ public void setFixedRateTasks(Map<Runnable, Long> fixedRateTasks) {
121121
this.fixedRateTasks = fixedRateTasks;
122122
}
123123

124+
/**
125+
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
126+
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
127+
*/
128+
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
129+
this.fixedDelayTasks = fixedDelayTasks;
130+
}
131+
124132
/**
125133
* Add a Runnable task to be triggered per the given {@link Trigger}.
126134
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
@@ -142,17 +150,6 @@ public void addCronTask(Runnable task, String cronExpression) {
142150
this.cronTasks.put(task, cronExpression);
143151
}
144152

145-
/**
146-
* Add a Runnable task to be triggered with the given fixed delay.
147-
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
148-
*/
149-
public void addFixedDelayTask(Runnable task, long delay) {
150-
if (this.fixedDelayTasks == null) {
151-
this.fixedDelayTasks = new HashMap<Runnable, Long>();
152-
}
153-
this.fixedDelayTasks.put(task, delay);
154-
}
155-
156153
/**
157154
* Add a Runnable task to be triggered at the given fixed-rate period.
158155
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
@@ -165,14 +162,20 @@ public void addFixedRateTask(Runnable task, long period) {
165162
}
166163

167164
/**
168-
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
165+
* Add a Runnable task to be triggered with the given fixed delay.
169166
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
170167
*/
171-
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
172-
this.fixedDelayTasks = fixedDelayTasks;
168+
public void addFixedDelayTask(Runnable task, long delay) {
169+
if (this.fixedDelayTasks == null) {
170+
this.fixedDelayTasks = new HashMap<Runnable, Long>();
171+
}
172+
this.fixedDelayTasks.put(task, delay);
173173
}
174174

175-
175+
/**
176+
* Schedule all registered tasks against the underlying {@linkplain
177+
* #setTaskScheduler(TaskScheduler) task scheduler.
178+
*/
176179
public void afterPropertiesSet() {
177180
if (this.taskScheduler == null) {
178181
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
@@ -200,7 +203,6 @@ public void afterPropertiesSet() {
200203
}
201204
}
202205

203-
204206
public void destroy() {
205207
for (ScheduledFuture<?> future : this.scheduledFutures) {
206208
future.cancel(true);

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,6 @@
1616

1717
package org.springframework.scheduling.config;
1818

19-
import org.w3c.dom.Element;
20-
import org.w3c.dom.Node;
21-
import org.w3c.dom.NodeList;
22-
2319
import org.springframework.beans.factory.config.RuntimeBeanReference;
2420
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
2521
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -28,6 +24,10 @@
2824
import org.springframework.beans.factory.xml.ParserContext;
2925
import org.springframework.util.StringUtils;
3026

27+
import org.w3c.dom.Element;
28+
import org.w3c.dom.Node;
29+
import org.w3c.dom.NodeList;
30+
3131
/**
3232
* Parser for the 'scheduled-tasks' element of the scheduling namespace.
3333
*
@@ -87,9 +87,8 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit
8787

8888
if (!(hasCronAttribute | hasFixedDelayAttribute | hasFixedRateAttribute | hasTriggerAttribute)) {
8989
parserContext.getReaderContext().error(
90-
"exactly one of the 'cron', 'fixed-delay', 'fixed-rate', or 'trigger' attributes is required", taskElement);
91-
// Continue with the possible next task element
92-
continue;
90+
"one of the 'cron', 'fixed-delay', 'fixed-rate', or 'trigger' attributes is required", taskElement);
91+
continue; // with the possible next task element
9392
}
9493

9594
if (hasCronAttribute) {

spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,15 +16,11 @@
1616

1717
package org.springframework.scheduling.annotation;
1818

19-
import static org.hamcrest.Matchers.greaterThan;
20-
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
21-
import static org.hamcrest.Matchers.startsWith;
22-
import static org.junit.Assert.assertThat;
23-
2419
import java.util.Date;
2520
import java.util.concurrent.atomic.AtomicInteger;
2621

2722
import org.junit.Test;
23+
2824
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2925
import org.springframework.context.annotation.Bean;
3026
import org.springframework.context.annotation.Configuration;
@@ -34,6 +30,10 @@
3430
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
3531
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
3632

33+
import static org.hamcrest.Matchers.*;
34+
35+
import static org.junit.Assert.*;
36+
3737
/**
3838
* Tests use of @EnableScheduling on @Configuration classes.
3939
*

0 commit comments

Comments
 (0)