I have implemented a sample spring scheduled task, with an applicationContext as follows,
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="cron" method="show" cron="0/10 * * * * ?"/>
<task:scheduled ref="cron" method="show2" cron="0/15 * * * * ?"/>
</task:scheduled-tasks>
<task:scheduler id="myScheduler" pool-size="10"/>
How can I stop this schedule method?
Inject the ThreadPoolTaskScheduler into another bean, and invoke shutdown(). If that isn't acceptable, you could configure the cron bean to accept a flag. For example:
public class Job() {
private final AtomicBoolean stop = new AtomicBoolean(false);
public void show() {
if (stop.get()) {
return;
}
...
}
public void stop() {
stop.set(true);
}
}
Note that this won't remove the job from the scheduler. The only way to prevent that would be to obtain a reference to the ScheduledFuture and call cancel().
Depends on what you mean by "stop".
Business Condition Stop:
Stop as result of a business condition, you should have those conditions evaluated in your methods and just simply not execute the code. This way you can stop unwanted execution at runtime, run your logic to handle the condition fail (logging,notification,etc) as a result.
Non Business Condition:
Externalize the chron expression to properties file or as I prefer a system variable in the JVM. Then you can just change the property value to a 9999 scenario to stop any execution.
System Variable Example.
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="cron" method="show" cron="#{systemProperties['chron1']}"/>
<task:scheduled ref="cron" method="show2" cron="#{systemProperties['chron2']}"/>
Related
The application I am working on receives notifications from external systems, which I want to process sequentially, since I am experiencing some deadlocks.
I am using the TaskExecutor from Spring which is the equivalent of the JDK 1.5's Executor.
I've implemented it in the following way:
I've a java interface containing 1 method:
public interface AsynchronousService {
void executeAsynchronously(Runnable task);
}
and the corresponding implementation:
public class AsynchronousServiceImpl implements AsynchronousService {
private TaskExecutor taskExecutor;
#Override
public void executeAsynchronously(Runnable task) {
taskExecutor.execute(task);
}
#Required
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
}
Here is the configuration of the TaskExecutor. I am not sure about this configuration. Since, I want the notifications to execute sequentially, I set 1 for both, corePoolSize and maxPoolSize. This means that only 1 thread will be created in the threadpool and retrieves the notifications sequentially from the queue. I also set "false" for "WaitForTasksToCompleteOnShutdown" in order not to shutdown after each task is executed, but rather when the spring context is destroyed. Am I generally correct with my assumptions?
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="1"/>
<property name="maxPoolSize" value="1"/>
<property name="WaitForTasksToCompleteOnShutdown" value="false"/>
</bean>
Here I execute then the code:
asynchronousService.executeAsynchronously(new Runnable() {
#Override
public void run() {
someMethod.processNotification(notification)
}
});
What do you think of my implementation? Did I miss something?
I am not sure if/where I need to implement some error-handling?
EDIT:
Is there any possibilty to tweak the implementation of the task-executor in spring to use a custom queue? Or how difficult is it to prioritize the tasks in the queue? I looked at some implementations but most of them implement the executor-service from sratch without using Spring.
The application I am working on receives notifications from external
systems, which I want to process sequentially, since I am experiencing
some deadlocks.
If you process sequentially, you don't need thread pool anyway.
Since, I want the notifications to execute sequentially, I set 1 for
both, corePoolSize and maxPoolSize
This will create a fixed pool size of 1. There's only one thread so it will execute sequentially
I also set "false" for "WaitForTasksToCompleteOnShutdown" in order not
to shutdown after each task is executed, but rather when the spring
context is destroyed
This is wrong. This flag tells the pool to wait for task completion on shutdown (Eg. If you call pool.shutdownNow(), the pool will wait for any executing threads)
And to summarize: Don't use thread pool if you want to execute one by one serially without concurrent
I have following configuration to run task--
<bean id="trendDataJob" class="com.ge.og.realtrack.scheduler.TrendDataJob"> </bean>
<task:scheduled-tasks>
<task:scheduled ref="trendDataJob" method="trendJob" cron="#{trendDataJob.configMap['corn_exp']}"></task:scheduled>
<task:scheduled ref="trendDataJob" method="metaDataTrendJob" cron="#{trendDataJob.configMap['metadata_corn_exp']}"></task:scheduled>
</task:scheduled-tasks>
cron expression for this is corn_exp=0 0/1 * * * ? to run every minute.
Here is problem as both method of trendDataJob schedule to run every minute but they are executing one after another first trendJob once its completed then its executing metaDataTrendJob i am not able to understand this behavior .
Also another problem is in case of method takes more than one minute to finish finish..its not triggering next call till current call finish and return.
By default the scheduler uses a ConcurrentTaskScheduler with a single thread. If you want another one configure it and pass it to the scheduled-tasks scheduler attribute.
The easiest way, in XML, is to use the scheduler element. (See this section in the reference guide).
<task:scheduler id="scheduler" pool-size="10"/>
Then simply register it on the other element.
<task:scheduled-tasks scheduler="scheduler"> ...
Have you used #EnableScheduling in your java code?
#EnableScheduling ensures that a background task executor is created. Without it, nothing gets scheduled.
For more, you can go through
Spring 3 #Scheduled – 4 Ways to Schedule Tasks
Spring Batch + Spring TaskScheduler example
Scheduling Tasks
Enable scheduling annotations
To enable support for #Scheduled and #Async annotations add #EnableScheduling and #EnableAsync to one of your #Configuration classes:
#Configuration
#EnableAsync
#EnableScheduling
public class AppConfig {
}
You are free to pick and choose the relevant annotations for your application. For example, if you only need support for #Scheduled, simply omit #EnableAsync. For more fine-grained control you can additionally implement the SchedulingConfigurer and/or AsyncConfigurer interfaces. See the javadocs for full details.
If you prefer XML configuration use the <task:annotation-driven> element.
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Notice with the above XML that an executor reference is provided for
handling those tasks that correspond to methods with the #Async
annotation, and the scheduler reference is provided for managing those
methods annotated with #Scheduled.
If you're using a default task scheduler in spring, i'm pretty sure it only runs on a single thread, hence why you cannot make them run in parallel.
You need to configure some kind of BatchScheduler with a pool size, to make it run in parallel.
I have defined a spring scheduler and it works automatically based on the cron i gave but i would like to call the scheduler from UI so that this scheduler can be run whenever some one wants to run.
<bean id="schedulerToCall" class="validPackagename.schedulerToCallTask" />
I would like to call this spring bean in some controller manually.
how to call that ?
Thanks
for example your context config is like this:
<bean id="schedulerToCall" class="validPackagename.SchedulerToCallTask" />
<task:scheduled-tasks>
<task:scheduled ref="schedulerToCall" method="runTaskMethod" cron="0 1 0 * * MON"/>
</task:scheduled-tasks>
In SchedulerToCallTask.java:
#Component
public class SchedulerToCallTask{
In the controller class you can just:
#Resource
SchedulerToCallTask schedulerToCallTask;
In the controller function you want to call this task:
schedulerToCallTask.runTaskMethod();
If I understood your query correctly. since cron runs based on the cron parameters, you need to pass the current time in the cron parameter. Also that cron parameters should be passed dynamically when the use want to run.
eg:
<task:scheduled ref="cronService" method="runCron" cron="* 0 0 * * ?"></task:scheduled>
I'm having an strange behavior with spring task schedule on jboss 6.3.0.GA. I don't know why everytime when a task is launched in jboss it's launched twice at same time, in tomcat just once a time.
<task:scheduler id="taskScheduler" pool-size="1"/>
<task:scheduled-tasks scheduler="taskScheduler">
<task:scheduled ref="jobListener" method="pickUpChanges" cron="*/5 * * * * ?"/>
</task:scheduled-tasks>
spring.version: 3.1.1.RELEASE
Any help?
You cannot have both scheduler corn expression and fixed-delay remove one of them.
<task:scheduled ref="jobListener" method="pickUpChanges" cron="*/5 * * * * ?"/>
or
<task:scheduled ref="jobListener" method="pickUpChanges" fixed-delay="3000"/>
Refer the link for more detials. In short in your case two triggers are triggered one for fixed-delay and other for cron expression resulting in two times execution of the method.
I have in my xml file something like
<task:scheduled-tasks scheduler="idOfScheduler">
<task:scheduled ref="myBean" method="update1" cron="...">
<task:scheduled ref="myBean" method="delete2" cron="...">
</task:scheduled-tasks>
<task:scheduler id="idOfScheduler" pool-size="5">
The problem is that when method update1 takes very long, method delete2 is not executed until update1 finishes. Is it because both tasks are scheduled in the same scheduler (it is configured with a max pool of 5)? Could one point out to the documentation that describes this part?