Spring supports Quartz so you can easily create batch jobs. These jobs may be triggered in time intervals or cron expressions. In context xml you can define these attributes. I want to explain how to change dynamically these definitions ,which is read from context xml.
First how to define a quartz job in context.xml ...You have to define JobDetailBean,SimpleTriggerBean and SchedulerFactoryBean :
<bean name="scheduledJob" id="scheduledJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.blogspot.devside.quartz.job.ScheduledJob"/>
</bean>
<bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="scheduledJob"/>
<property name="startDelay" ref="2000" />
<property name="repeatInterval" ref="2000"/>
</bean>
<bean id="schedulerFactory" name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" scope="singleton">
<property name="triggers">
<list>
<ref bean="trigger"/>
</list>
</property>
</bean>
And our ScheduledJob class .It will only print current time in seconds.
public class ScheduledJob extends QuartzJobBean{
static SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
System.out.println("Scheduled job - Current Millis : " + format.format(new Date(System.currentTimeMillis())) );
}
}
Then we need Runny class which has a main method.
public class Runny {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("/applicationContext.xml");
}
}
If you run the runny class, you will see the result , looks like the following lines.
Scheduled job - Current Millis : 10:51:27
Scheduled job - Current Millis : 10:51:29
Scheduled job - Current Millis : 10:51:31
Scheduled job - Current Millis : 10:51:33
Scheduled job - Current Millis : 10:51:35
...
Now we have a quartz job which runs in every 3 seconds. 3 seconds time interval is defined in context xml . It is static. Now what if we want to retrieve time interval value from a database or another source and change it dynamically.
First , we have to get the value from a bean (bean can get value from database , web service,etc...) ,we will use method invocation for this.
Second , we will change repeatInterval and startDelay . SchedulerFactoryBean will be singleton so we can get trigger and change its values.
Our new context xml will be like the following lines :
<bean id="scheduledJobDef" name="scheduledJobDef" class="com.blogspot.devside.quartz.job.ScheduledJobDef"/>
<bean id="rescheduler" name="rescheduler" class="com.blogspot.devside.quartz.Rescheduler">
<property name="schedulerFactory" ref="schedulerFactory"></property>
<property name="scheduledJobDef" ref="scheduledJobDef"></property>
</bean>
<bean name="scheduledJob" id="scheduledJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.blogspot.devside.quartz.job.ScheduledJob"/>
</bean>
<bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="scheduledJob"/>
<property name="startDelay" ref="startDelayMethod" />
<property name="repeatInterval" ref="repeatIntervalMethod"/>
</bean>
<bean id="schedulerFactory" name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" scope="singleton">
<property name="triggers">
<list>
<ref bean="trigger"/>
</list>
</property>
</bean>
<bean id="repeatIntervalMethod"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="scheduledJobDef" />
</property>
<property name="targetMethod">
<value>getFirstRepeatInterval</value>
</property>
<property name="arguments">
<list />
</property>
</bean>
<bean id="startDelayMethod"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref local="scheduledJobDef" />
</property>
<property name="targetMethod">
<value>getFirstStartDelay</value>
</property>
<property name="arguments">
<list />
</property>
</bean>
Scheduled JobDef class :
public class ScheduledJobDef {
public long getFirstStartDelay(){
return 2000;
}
public long getFirstRepeatInterval(){
return 2000;
}
public long getStartDelay(){
return 5000;
}
public long getRepeatInterval(){
return 5000;
}
}
MethodInvocationFactoryBean beans will invoke getFirstStartDelay and getFirstRepeatInterval.
Rescheduler class :
public class Rescheduler {
StdScheduler schedulerFactory;
ScheduledJobDef scheduledJobDef;
public void reschedule(){
System.out.println(schedulerFactory);
try {
SimpleTriggerBean t = (SimpleTriggerBean) schedulerFactory
.getTrigger("trigger", Scheduler.DEFAULT_GROUP);
JobDetail job = schedulerFactory.getJobDetail(t.getJobDetail()
.getName(), t.getJobDetail().getGroup());
t.setRepeatInterval(scheduledJobDef.getRepeatInterval());
t.setStartDelay(scheduledJobDef.getStartDelay());
t.setStartTime(new Date( System.currentTimeMillis()));
schedulerFactory.rescheduleJob(t.getName(), Scheduler.DEFAULT_GROUP, t);
schedulerFactory.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public StdScheduler getSchedulerFactory() {
return schedulerFactory;
}
public void setSchedulerFactory(StdScheduler schedulerFactory) {
this.schedulerFactory = schedulerFactory;
}
public ScheduledJobDef getScheduledJobDef() {
return scheduledJobDef;
}
public void setScheduledJobDef(ScheduledJobDef scheduledJobDef) {
this.scheduledJobDef = scheduledJobDef;
}
}
In reschedule method , trigger retrieved from singleton SchedulerFactoryBean then its values are changed.Trigger is rescheduled and started.
New lines must be added to Runny class ,
public class Runny {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("/applicationContext.xml");
Thread.sleep(10000);
Rescheduler rescheduler = (Rescheduler) ctx.getBean("rescheduler");
rescheduler.reschedule();
Thread.sleep(10000);
}
}
There are two sleep because I want to show difference between before and after trigger rescheduled.
System out will look like the following lines :
Scheduled job - Current Millis : 11:09:46
Scheduled job - Current Millis : 11:09:48
Scheduled job - Current Millis : 11:09:50
Scheduled job - Current Millis : 11:09:52
Scheduled job - Current Millis : 11:09:54
org.quartz.impl.StdScheduler@dc57db
Scheduled job - Current Millis : 11:09:54
Scheduled job - Current Millis : 11:09:59
Scheduled job - Current Millis : 11:10:04
..
As you can see , after reschedule progress is done , time interval changed as 5 seconds.
Bài post của tác giả quá hữu ích, thank bạn đã share.
YanıtlaSilXem tại website : Giá đá thạch anh vụn
Bài post của Bạn quá hay, cám ơn bạn đã chia sẻ.
YanıtlaSilXem tại website : Chế tác đá thạch anh
Bài post của tác giả hay, thank anh đã share.
YanıtlaSilThông tin thêm : Tỳ hưu đá thạch anh
It's very good tutorial sir, but i have a question. What changes should i make in order to run project if i want to add Tomcat Local Server, because i don't have main class.
YanıtlaSilIt's very good tutorial sir, but i have a question. What changes should i make in order to run project if i want to add Tomcat Local Server, because i don't have main class.
YanıtlaSil