Not all applications are driven by user input. Some applications need to execute without any user intervention probably running at the background at specified intervals. For instance, a Virus Scanner application will be running in the background once in 2 days. Another instance could be where a Software could connect to its server repository once in a day for any updates. In this article we will see how Spring provides integration support for JDK Timer and Quartz that facilitates in writing job scheduling applications. The first half of the article draws an example for writing an application that uses JDK Timer with Spring support. The later section of the article discusses in writing an application that uses Quartz scheduling with some basic level of understanding done of cron expressions.
also read:
Integrating JDK Timer with Spring Framework
In this section, we will see how to integrate Spring with JDK Timer task objects. JDK Timer task objects provide support for execution of any task driven by a timer. Let us assume that we want to write a service that will periodically check for internet connection and logs the connection status. We will also imagine that this service has to run periodically all through the day with an interval of 30 minutes.
Writing the service
Following class provides the listing representing the internet connection service.
InternetConnectionCheckService.java
package net.javabeat.articles.spring.core.scheduling.timer; import java.net.URL; import java.net.URLConnection; import java.util.Date; public class InternetConnectionCheckService { public void checkConnection(){ if (doCheck()){ System.out.println(new Date() + " Internet connection available"); }else{ System.out.println(new Date() + " Internet connection not available"); } } private boolean doCheck(){ URL urlObject = null; URLConnection urlConnection = null; try{ urlObject = new URL("http://www.google.com"); urlConnection = urlObject.openConnection(); urlConnection.getContent(); return true; }catch (Exception exception){ return false; } } }
The above code is fairly simple. To check whether internet connection is available or not it opens up a connection to a well-known domain for getting the content in the doCheck()
method. When the connection is a failure, exception will be thrown which means that the connection is not available.
Wrapping service as a timer task
Now that we have written a service, we will see how to wrap the service as a task that can be driven from a timer. Refer the following code,
InternetConnectionCheckTimerTask.java
package net.javabeat.articles.spring.core.scheduling.timer; import java.util.TimerTask; public class InternetConnectionCheckTimerTask extends TimerTask{ private InternetConnectionCheckService service; public InternetConnectionCheckService getService() { return service; } public void setService(InternetConnectionCheckService service) { this.service = service; } @Override public void run() { service.checkConnection(); } }
We have written a timer task class which extends the java.util.TimerTask
class. The run()
method is overridden for performing any operation. In this case, the operation will be calling the internet connection service to check for the connection status. Note that timer task is dependant on internet connection service object. Later on, we will see how to wire both these objects.
Configuration
So far we haven’t specified the repeating interval of 30 minutes at which the service has to be executed. In fact, Spring already provides the support through configuration. Have a look at the following configuration file representing the application’s context.
timer.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="connectionCheckService"> </bean> <bean id="connectionCheckTimerTask"> <property name="service" ref="connectionCheckService" /> </bean> <bean id="scheduledConnectionCheckTimerTask"> <property name="delay" value="2000" /> <property name="period" value="30000" /> <property name="timerTask" ref="connectionCheckTimerTask" /> </bean> <bean> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledConnectionCheckTimerTask"/> </list> </property> </bean> </beans>
We have declared the bean connectionCheckService
representing the internet connection service. The second bean declaration defines the timer task with the bean id connectionCheckTimerTask
. Because timer task is dependent on internet connection service, the dependency is injected through configuration.
Have a look at the following code snippet which declares the scheduled timer task object from Spring.
<bean id="scheduledConnectionCheckTimerTask"> <property name="delay" value="2000" /> <property name="period" value="30000" /> <property name="timerTask" ref="connectionCheckTimerTask" /> </bean>
This class org.springframework.scheduling.timer.ScheduledTimerTask
provides scheduling support for the execution of timer tasks. The property delay
specified in milliseconds specifies the initial delay after which the task has to be executed. The value is mentioned as 2000
which means after the initial delay for the execution of the task will be 2 seconds. Next comes the property period
which is also specified in milliseconds and that represents the interval after which the task will be repeatedly execution. In our case, the value given is 3000
, so for every 30 minutes the task for execution will be fired. The final property is the timerTask
which should point to the actual the timer task object, in this case it is going to be the connectionCheckTimerTask
.
Triggering the scheduled tasks is done by TimerFactoryBean
. It takes a list of scheduled timer task objects, in our case there is only one scheduled timer task object which is scheduledConnectionCheckTimerTask
.
<bean> <property name="scheduledTimerTasks"> <list> <ref bean="scheduledConnectionCheckTimerTask"/> </list> </property> </bean>
Client
The client application in this example is going to do nothing other than just loading the application’s context. As soon the context is loaded service object, timer task object, scheduled timer task objects will be loaded and wired. Because we have also introduced the trigger bean which will trigger the scheduled timer task for execution, the internet connection will be running indefinitely with an interval of 30 minutes.
Client.java
package net.javabeat.articles.spring.core.scheduling.timer; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("timer.xml"); } }
Spring Integration with Quartz
In this section, we will see how to integrate Spring with Quartz scheduling support. Quartz is extremely robust and powerful with advanced features such as distributed transactions and persistent jobs, the scope of which is completely outside of this article. We will write an example which will trigger an application for receiving work status for all the employees on all the business days (i.e from Monday till Friday) at 11 AM and 6PM.
Writing the service
Since the focus is more on explaining the advanced scheduling support, this service will do nothing other than printing on the console that the service has been invoked at appropriate hours.
StatusUpdateService.java
package net.javabeat.articles.spring.core.scheduling.quartz; import java.util.Date; public class StatusUpdateService { public void updateStatus(){ System.out.println(new Date() + " Update status Service invoked"); } }
Wrapping service in a job bean
A Job Bean in Quartz encapsulates the task for execution and in our case, the task is as simple as calling the status update service. Have a look at the status update job bean.
StatusUpdateJobBean.java
package net.javabeat.articles.spring.core.scheduling.quartz; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class StatusUpdateJobBean extends QuartzJobBean{ private StatusUpdateService service; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { service.updateStatus(); } public StatusUpdateService getService() { return service; } public void setService(StatusUpdateService service) { this.service = service; } }
Note that a job bean must extend QuartzJobBean and the method executeInternal()
should be overridden for a job to execute. Note that later on in the configuration file we will see how the dependency between status update service and status update job bean is resolved.
Configuration
The configuration file provides the declaration of beans, wiring the dependency between beans as well the scheduling support for job execution. Have a look at the listing.
quartz.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="statusUpdateService"> </bean> <bean id="statusUpdateJob"> <property name="jobClass" value="net.javabeat.articles.spring.core.scheduling.quartz.StatusUpdateJobBean" /> </bean> <bean id="statusUpdateTriggerBean"> <property name="jobDetail" ref="statusUpdateJob"/> <property name="cronExpression" value="0 0 11,18 ? * MON-FRI *" /> </bean> <bean> <property name="triggers"> <list> <ref bean="statusUpdateTriggerBean"/> </list> </property> </bean> </beans>
The first bean declaration with the id statusUpdateService
declares an instance of StatusUpdateService
service which has the core logic for the execution of a job. Next comes the declaration of JobDetailBean
which is declared as follows,
<bean id="statusUpdateJob"> <property name="jobClass" value="net.javabeat.articles.spring.core.scheduling.quartz.StatusUpdateJobBean" /> </bean>
The mandatory property for this job bean is jobClass
. The property jobClass
takes the fully qualified name of the JobBean
which acts as wrapper in delegating the call to the real task of execution, in our case, the class name is net.javabeat.articles.spring.core.scheduling.quartz.StatusUpdateJobBean
.
Next comes the declaration of the CronTriggerBean which will be acting as a scheduler providing the time period and interval on which the job has to be executed. This bean takes the mandatory properties jobDetail
and cronExpression
. The property jobDetail
takes a reference to the job detail object that was just declared. The cronExpression
property specifies the interval at which the job has to be executed. Here the value given is “0 0 11,18 ? * MON-FRI *”. This value has 7 parts with space as a delimiter the meaning of which is given as follows
- First Field – Seconds
- Second Field – Minutes
- Third Field – Hours
- Fourth Field – Day of the Month
- Fifth Field – Month
- Sixth Field – Day of week
- Seventh Field – Year
Every value in the field can either take a single value (Eg: 1), comma-separated (Eg: 1,3,5) or range-based (Eg: 1-10). There are wild-card charactes ‘*’ and ‘?’ carrying special meaning. When ‘*’ is used against a field, it indicates all the values. For example, when ‘*’ is used for the third field, then it mean for all hours or for every hours. When ‘?’ is used it indicates that the field doesn’t carry any value.
So, coming back to our example, the value specified is “0 0 11,18 ? * MON-FRI *” which means “For every second in every minute, but during the hours 11 AM and 6 PM (not considering any day in a month), for all the months ranging from Monday till Friday in every Year” execute the given task.
also read:
Conclusion
We have seen how to write Job Scheduling applications with JDK Timer and Quartz objects with the help of Spring. It can be seen that for an application requiring basic scheduling support, it is wise to choose JDK Timer, however for applications that requires more sophisticated scheduling support; it is preferable to choose Quartz.