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
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,11 +24,11 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation that marks a method to be scheduled. Exactly one of the
|
||||
* <code>cron</code>, <code>fixedDelay</code>, or <code>fixedRate</code>
|
||||
* attributes must be provided.
|
||||
* {@link #cron()}, {@link #fixedDelay()}, or {@link #fixedRate()}
|
||||
* attributes must be specified.
|
||||
*
|
||||
* <p>The annotated method must expect no arguments and have a
|
||||
* <code>void</code> return type.
|
||||
* {@code void} return type.
|
||||
*
|
||||
* <p>Processing of {@code @Scheduled} annotations is performed by
|
||||
* registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
|
||||
@@ -49,9 +49,10 @@ public @interface Scheduled {
|
||||
/**
|
||||
* A cron-like expression, extending the usual UN*X definition to include
|
||||
* triggers on the second as well as minute, hour, day of month, month
|
||||
* and day of week. e.g. <code>"0 * * * * MON-FRI"</code> means once
|
||||
* per minute on weekdays (at the top of the minute - the 0th second).
|
||||
* and day of week. e.g. {@code "0 * * * * MON-FRI"} means once per minute on
|
||||
* weekdays (at the top of the minute - the 0th second).
|
||||
* @return an expression that can be parsed to a cron schedule
|
||||
* @see org.springframework.scheduling.support.CronSequenceGenerator
|
||||
*/
|
||||
String cron() default "";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.scheduling.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@@ -104,7 +105,6 @@ public class ScheduledAnnotationBeanPostProcessor
|
||||
return LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
@@ -124,9 +124,11 @@ public class ScheduledAnnotationBeanPostProcessor
|
||||
// found a @Scheduled method on the target class for this JDK proxy -> is it
|
||||
// also present on the proxy itself?
|
||||
method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
catch (SecurityException ex) {
|
||||
ReflectionUtils.handleReflectionException(ex);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"@Scheduled method '%s' found on bean target class '%s', " +
|
||||
"but not found in any interface(s) for bean JDK proxy. Either " +
|
||||
@@ -137,7 +139,7 @@ public class ScheduledAnnotationBeanPostProcessor
|
||||
}
|
||||
Runnable runnable = new ScheduledMethodRunnable(bean, method);
|
||||
boolean processedSchedule = false;
|
||||
String errorMessage = "Exactly one of 'cron', 'fixedDelay', or 'fixedRate' is required.";
|
||||
String errorMessage = "Exactly one of the 'cron', 'fixedDelay', or 'fixedRate' attributes is required.";
|
||||
String cron = annotation.cron();
|
||||
if (!"".equals(cron)) {
|
||||
processedSchedule = true;
|
||||
@@ -170,7 +172,8 @@ public class ScheduledAnnotationBeanPostProcessor
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, SchedulingConfigurer> configurers = applicationContext.getBeansOfType(SchedulingConfigurer.class);
|
||||
Map<String, SchedulingConfigurer> configurers =
|
||||
this.applicationContext.getBeansOfType(SchedulingConfigurer.class);
|
||||
|
||||
if (this.cronTasks.isEmpty() && this.fixedDelayTasks.isEmpty() &&
|
||||
this.fixedRateTasks.isEmpty() && configurers.isEmpty()) {
|
||||
@@ -190,19 +193,23 @@ public class ScheduledAnnotationBeanPostProcessor
|
||||
configurer.configureTasks(this.registrar);
|
||||
}
|
||||
|
||||
if (registrar.getScheduler() == null) {
|
||||
if (this.registrar.getScheduler() == null) {
|
||||
Map<String, ? super Object> schedulers = new HashMap<String, Object>();
|
||||
schedulers.putAll(applicationContext.getBeansOfType(TaskScheduler.class));
|
||||
schedulers.putAll(applicationContext.getBeansOfType(ScheduledExecutorService.class));
|
||||
if (schedulers.size() == 0) {
|
||||
// do nothing -> fall back to default scheduler
|
||||
} else if (schedulers.size() == 1) {
|
||||
}
|
||||
else if (schedulers.size() == 1) {
|
||||
this.registrar.setScheduler(schedulers.values().iterator().next());
|
||||
} else if (schedulers.size() >= 2){
|
||||
throw new IllegalStateException("More than one TaskScheduler and/or ScheduledExecutorService " +
|
||||
"exist within the context. Remove all but one of the beans; or implement the " +
|
||||
"SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler " +
|
||||
"explicitly within the configureTasks() callback. Found the following beans: " + schedulers.keySet());
|
||||
}
|
||||
else if (schedulers.size() >= 2){
|
||||
throw new IllegalStateException(
|
||||
"More than one TaskScheduler and/or ScheduledExecutorService " +
|
||||
"exist within the context. Remove all but one of the beans; or " +
|
||||
"implement the SchedulingConfigurer interface and call " +
|
||||
"ScheduledTaskRegistrar#setScheduler explicitly within the " +
|
||||
"configureTasks() callback. Found the following beans: " + schedulers.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,12 +19,15 @@ package org.springframework.scheduling.annotation;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration}
|
||||
* classes annotated with @{@link EnableScheduling} that wish to register scheduled tasks
|
||||
* in a <em>programmatic</em> fashion as opposed to the <em>declarative</em> approach of
|
||||
* using the @{@link Scheduled} annotation. For example, this may be necessary when
|
||||
* implementing {@link org.springframework.scheduling.Trigger Trigger}-based tasks, which
|
||||
* are not supported by the {@code @Scheduled} annotation.
|
||||
* Optional interface to be implemented by @{@link
|
||||
* org.springframework.context.annotation.Configuration Configuration} classes annotated
|
||||
* with @{@link EnableScheduling}. Typically used for setting a specific
|
||||
* {@link org.springframework.scheduling.TaskScheduler TaskScheduler} bean to be used when
|
||||
* executing scheduled tasks or for registering scheduled tasks in a <em>programmatic</em>
|
||||
* fashion as opposed to the <em>declarative</em> approach of using the @{@link Scheduled}
|
||||
* annotation. For example, this may be necessary when implementing {@link
|
||||
* org.springframework.scheduling.Trigger Trigger}-based tasks, which are not supported by
|
||||
* the {@code @Scheduled} annotation.
|
||||
*
|
||||
* <p>See @{@link EnableScheduling} for detailed usage examples.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -65,7 +65,7 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
|
||||
|
||||
/**
|
||||
* Set the TaskScheduler to register scheduled tasks with.
|
||||
* Set the {@link TaskScheduler} to register scheduled tasks with.
|
||||
*/
|
||||
public void setTaskScheduler(TaskScheduler taskScheduler) {
|
||||
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
|
||||
@@ -73,9 +73,9 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link org.springframework.scheduling.TaskScheduler} to register scheduled
|
||||
* tasks with, or a {@link java.util.concurrent.ScheduledExecutorService} to be
|
||||
* wrapped as a TaskScheduler.
|
||||
* Set the {@link TaskScheduler} to register scheduled tasks with, or a
|
||||
* {@link java.util.concurrent.ScheduledExecutorService} to be wrapped as a
|
||||
* {@code TaskScheduler}.
|
||||
*/
|
||||
public void setScheduler(Object scheduler) {
|
||||
Assert.notNull(scheduler, "Scheduler object must not be null");
|
||||
@@ -91,7 +91,7 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scheduler instance for this registrar (may be null)
|
||||
* Return the {@link TaskScheduler} instance for this registrar (may be {@code null}).
|
||||
*/
|
||||
public TaskScheduler getScheduler() {
|
||||
return this.taskScheduler;
|
||||
@@ -121,6 +121,14 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
this.fixedRateTasks = fixedRateTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
|
||||
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
|
||||
*/
|
||||
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
|
||||
this.fixedDelayTasks = fixedDelayTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Runnable task to be triggered per the given {@link Trigger}.
|
||||
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
|
||||
@@ -142,17 +150,6 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
this.cronTasks.put(task, cronExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Runnable task to be triggered with the given fixed delay.
|
||||
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
|
||||
*/
|
||||
public void addFixedDelayTask(Runnable task, long delay) {
|
||||
if (this.fixedDelayTasks == null) {
|
||||
this.fixedDelayTasks = new HashMap<Runnable, Long>();
|
||||
}
|
||||
this.fixedDelayTasks.put(task, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Runnable task to be triggered at the given fixed-rate period.
|
||||
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
|
||||
@@ -165,14 +162,20 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
|
||||
* Add a Runnable task to be triggered with the given fixed delay.
|
||||
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
|
||||
*/
|
||||
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
|
||||
this.fixedDelayTasks = fixedDelayTasks;
|
||||
public void addFixedDelayTask(Runnable task, long delay) {
|
||||
if (this.fixedDelayTasks == null) {
|
||||
this.fixedDelayTasks = new HashMap<Runnable, Long>();
|
||||
}
|
||||
this.fixedDelayTasks.put(task, delay);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Schedule all registered tasks against the underlying {@linkplain
|
||||
* #setTaskScheduler(TaskScheduler) task scheduler.
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
if (this.taskScheduler == null) {
|
||||
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||
@@ -200,7 +203,6 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
for (ScheduledFuture<?> future : this.scheduledFutures) {
|
||||
future.cancel(true);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
package org.springframework.scheduling.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -28,6 +24,10 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Parser for the 'scheduled-tasks' element of the scheduling namespace.
|
||||
*
|
||||
@@ -87,9 +87,8 @@ public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefini
|
||||
|
||||
if (!(hasCronAttribute | hasFixedDelayAttribute | hasFixedRateAttribute | hasTriggerAttribute)) {
|
||||
parserContext.getReaderContext().error(
|
||||
"exactly one of the 'cron', 'fixed-delay', 'fixed-rate', or 'trigger' attributes is required", taskElement);
|
||||
// Continue with the possible next task element
|
||||
continue;
|
||||
"one of the 'cron', 'fixed-delay', 'fixed-rate', or 'trigger' attributes is required", taskElement);
|
||||
continue; // with the possible next task element
|
||||
}
|
||||
|
||||
if (hasCronAttribute) {
|
||||
|
||||
Reference in New Issue
Block a user