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>
Related
<task:scheduled-tasks>
<task:scheduled ref="testBean" method="testMethod" fixed-rate="1000"/>
</task:scheduled-tasks>
In the above snippet, I want to pass fixed-rate as variable fetched from the config file. How can I do that?
P.S. I don't want to move to the annotation-based scheduler.
After going through various articles and documentation I found a way to achieve the same. So sharing the same.
I created a configuration bean of a loader class. Loader class is responsbile to fetch the configs (either from file or any configuration management tool) and set in the system properties.
<bean id="configuration" class="com.test.config.loader">
</bean>
Say one the property is like
database:mysql
It can be accessed like
<task:scheduled-tasks>
<task:scheduled ref="testBean" method="testMethod" fixed-rate="#{configuration['database']}"/>
</task:scheduled-tasks>
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 a situation where a particular file is to be copied from a location to another. The polling is not required as the action will be deliberately triggered. Also the directory from which the file is to be picked up is decided at run time.
I can have a configuration as follows:
<int-file:inbound-channel-adapter id="filesIn" directory="#outPathBean.getPath()" channel="abc" filter="compositeFilter" >
<int:poller id="poller" fixed-delay="5000" />
</int-file:inbound-channel-adapter>
<int:channel id="abc"/>
<int-file:outbound-channel-adapter channel="abc" id="filesOut"
directory-expression="file:${paths.root}"
delete-source-files="true" filename-generator="fileNameGenerator" />
filenamegenerator and composite filter classes are configured as well.
I am new to spring. Please point me in the right direction!!
You can use a FireOnceTrigger as discussed in this answer and start/stop the adapter as needed.
To get a reference to the adapter (a SourcePollingChannelAdapter), inject (or #Autowire etc.) it as a Lifecycle bean (start()/stop() etc).
Or you can do the whole thing programmatically using a FileReadingMessageSource, and discussed in this answer.
Sample for start/stop Adapter.incase its useful.
SourcePollingChannelAdapter sourcePollingChannelAdapter = (SourcePollingChannelAdapter) context
.getBean("filesIn"); //adapter id in the bean configuration
// Stop
if (sourcePollingChannelAdapter.isRunning()) {
sourcePollingChannelAdapter.stop();
}
// Set Cron Expression if required when start or use any triggers
CronTrigger cronTrigger = new CronTrigger("* * * * * ?");
sourcePollingChannelAdapter.setTrigger(cronTrigger);
// Start
if (!sourcePollingChannelAdapter.isRunning()) {
sourcePollingChannelAdapter.start();
}
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']}"/>
I need to configure a scheduling algorithm that is beyond the capabilities of Spring's in-build scheduling (basically "every 5 minutes, but only between 4:00h and 16:00h"). It seems that implementing the org.springframework.scheduling.Trigger interface is the way to go, which seems simple enough.
The part I can't figure out and that doesn't seem to be answered in the documentation is: how does this mix with the XML configuration? There doesn't seem to be any way of specifying a custom trigger bean in the elements of the task namespace (apart from the Quartz example).
How do I use a custom trigger in a Spring 3 application? Ideally using the Bean XML configuration.
Take a look at DurationTrigger I wrote a year ago.
public class DurationTrigger implements Trigger {
/**
* <p> Create a trigger with the given period, start and end time that define a time window that a task will be
* scheduled within.</p>
*/
public DurationTrigger( Date startTime, Date endTime, long period ) {...}
// ...
}
Here is how you would schedule such a task with this trigger:
Trigger trigger = new DurationTrigger( startTime, endTime, period );
ScheduledFuture task = taskScheduler.schedule( packageDeliveryTask, trigger );
Alternatively, you can use a CronTrigger / cron expression:
<!-- Fire every minute starting at 2:00 PM and ending at 2:05 PM, every day -->
<task:scheduled-tasks>
<task:scheduled ref="simpleProcessor" method="process" cron="0 0-5 14 * * ?"/>
</task:scheduled-tasks>
Check out this JIRA as well as this Spring Integration article
EDIT:
From the JIRA discussion, you can configure the DurationTrigger above, or any other custom trigger for that matter, using Spring Integration:
<inbound-channel-adapter id="yourChannelAdapter"
channel="yourChannel">
<poller trigger="durationTrigger"/>
</inbound-channel-adapter>
<beans:bean id="durationTrigger" class="org.gitpod.scheduler.trigger.DurationTrigger">
<beans:constructor-arg value="${start.time}"/>
<beans:constructor-arg value="${end.time}"/>
<beans:constructor-arg value="${period}"/>
</beans:bean>
It is quite simple to use Spring Integration in your project, even if you did not plan to. You can use as little as the above scheduling piece, or as much as relying on many other Enterprise Integration patterns that Spring Integration has available.
It seems using XML to configure any but the two standard triggers is not possible in Spring 3.0. It has been added as a new feature in the 3.1M2 release, though: https://jira.springsource.org/browse/SPR-8205
Thanks to Mark Fisher for pointing this out.