In my application there is a requirement to be able to create Scheduled Job(s) for My sql database autobackup
Can I use Spring Quartz Scheduling to create this Jobs?
Any help would be useful.
Amulraj.P
Yes you can, though it seems a bit overkill. Backuping an MSSQL db can be done using commandline tools, which you can easily schedule to run using cron if you are using Unix or Scheduled Tasks on Windows.
%PATH_TO_SQL_SERVER%\Tools\Binn\osql.exe
-E -Q "BACKUP DATABASE mydb TO DISK='%PATH_TO_BKP%\db.bak' WITH FORMAT"
For you question the answer is something like this: (shameless self-copy from here)
The job referring to your business object which has the method which takes care of the backup:
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject" />
<property name="targetMethod" value="backupDB" />
<property name="concurrent" value="false" />
</bean>
The trigger that takes care of firing the method:
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="exampleJob" />
<!-- run every morning at 6 AM, use regular cron expressions-->
<property name="cronExpression" value="0 0 6 * * ?" />
</bean>
The schedulerFactoryBean for wiring the trigger:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
See further in Spring documentation for 2.5, here for 3.0.
Related
I need to create a batch job that reads from the database millions of rows and I am thinking which is the best approach to do it the fastest that can be done; I think that using sql native to read will be the best option but I am also want to know more infos about the spring batch configuration and I don't seem to finding what I am searching for.
I know there are 2 ways of reading data in a Spring batch job using a Reader.
inside a bean eg:
<batch:step id="fetchData" >
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="dataReader" processor="dataProcessor"
writer="dataWriter" commit-interval="100"/>
</batch:tasklet>
<bean id="dataReader"
class="org.springframework.batch.item.database.JdbcPagingItemReader"
scope="step">
<property name="dataSource" ref="dataSourceNative"/>
<property name="pageSize" value="100"/>
<property name="rowMapper" ref="RowsMapper"/>
<property name="queryProvider">
<bean class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSourceNative"/>
<property name="selectClause"
value="SELECT a,b "/>
<property name="fromClause"
value="from table"/>
<property name="whereClause"
value="WHERE a="blabla"/>
</bean>
</property>
</bean>
using a Java Class
<property name="targetObject" ref="myClassDao" />
<property name="targetMethod" value="list" />
<property name="arguments">
<list>
<!-- add arguments list -->
</list>
</property>
</bean>
<bean id="myClassDao" class="path.to.MyClassDAO"
Is it the same thing to do any of this approaches or the 2nd one gives you more liberty?
If the answer is no, which option is better/fastest?
I am thinking if I want to read from the database but using hibernate to do it. Can be implemented with any of these approaches?
We need to add the startTime for spring quartz scheduler. Lets assume the below bean as CronTriggerFactoryBean. And we need to start the scheduler after 5 days of server starting time.
<bean id="sampleBean"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="beanManager"/>
<property name="targetMethod" value="beanMethod"/>
<property name="concurrent" value="false"/>
</bean>
</property>
<property name="cronExpression" value="0 0/30 * ? * SUN-FRI"/>
</bean>
And above scheduler configuration doesn't start when application server get started. Its running like
Let's assume server start at 12:03 PM.
Scheduler invoking at 12:30, 13:00, 13:30, 14:00 ... respectively.
But what we want is server start at 12:03 PM means the scheduler should run once at the time of server starting and the following time too 12:33, 13:03, 13:33, 14:03 ...
Will it work when we are setting the startTime for this bean?
You should use SimpleTriggerFactoryBean instead of CronTriggerFactoryBean and define a trigger like this:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="simpleJobDetail" />
<property name="startDelay" value="1000" />
<property name="repeatInterval" value="10000" />
</bean>
This will run the job every 10 seconds with initial delay of 1 second from server start. Now adjust the values as per your requirements.
I’m using Spring 3.2.11.RELEASE. I currently have the following set up in my application context file for the purposes of loading a cron trigger based off a schedule defined in a properties file (the property = cron.schedule) …
<bean id="localPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
</bean>
…
<bean id="updateResourcesJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myService" />
<property name="targetMethod" value="myMethod" />
<property name="concurrent" value="true" />
</bean>
<bean id="updateResourcesCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="myJob" />
<property name="cronExpression" value="${cron.schedule}" />
</bean>
My question is, I would like to create an XML configuration in my context file that allows me to edit my properties file and have everything automatically reloaded without having to restart my server or re-deploy my application. I have read several places about Apache Commons Configuration, but I can’t figure out how to take the above and rewrite an XML config that would utilize the configuration.
Thanks for any help, - Dave
I have a problem with load-balancing Quartz jobs. When there are two instances running, only one of them handles all jobs. The second one is idling. When I terminate first instance the second one starts to handle jobs until first instance is started again.
I expected that there is kind of load-balancing which dispatches jobs between those two instances.
I am using Quartz version 1.8.6.
This is the part of applicationContext.xml:
<bean id="firstJobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mycompany.quartz.job.FirstJob" />
<property name="durability" value="true" />
</bean>
<bean id="firstTrigger" class="com.mycompany.quartz.PersistableCronTriggerFactoryBean">
<property name="jobDetail" ref="firstJobDetail" />
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
<bean id="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:META-INF/quartz.properties" />
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<!-- This name is persisted as SCHED_NAME in db. for local testing could
change to unique name to avoid collision with dev server -->
<property name="schedulerName" value="quartzScheduler" />
<!-- Will update database cron triggers to what is in this jobs file on
each deploy. Replaces all previous trigger and job data that was in the database.
YMMV -->
<property name="overwriteExistingJobs" value="true" />
<property name="autoStartup" value="true" />
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="jobFactory">
<bean class="com.mycompany.quartz.AutowiringSpringBeanJobFactory" />
</property>
<!-- NOTE: Must add both the jobDetail and trigger to the scheduler! -->
<property name="jobDetails">
<list>
<ref bean="firstJobDetail" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="firstTrigger" />
</list>
</property>
</bean>
And this is the quartz.properties file:
# Spring uses LocalDataSourceJobStore extension of JobStoreCMT
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
# Change this to match your DB vendor
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# Needed to manage cluster instances
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=MY_JOB_SCHEDULER
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
According to the documentation, you need to set org.quartz.jobStore.clusterCheckinInterval .
I Know it is too late to answer your question. But recently I come across the same issue and found your post in online.
Whenever there are two instances running, either one of them tries to put lock on the job. Since your trigger time is every 10 secs which is very less (0/10 * * * * ?), the instance 2 is unable to put lock on the job.
Increase the time period to one minute(* 0/1 * * * ?). You can see, both the instance will process the job.
Please let me know if you face any other issues.
Documentation says:
Load-balancing occurs automatically, with each node of the cluster
firing jobs as quickly as it can. [...] Only one node will fire the
job for each firing. [...] It won’t necessarily be the same node each
time - it will more or less be random which node runs it. The load
balancing mechanism is near-random for busy schedulers (lots of
triggers) but favors the same node for non-busy (e.g. few triggers)
schedulers.
<bean name="MyJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.package.scheduler.MyJob"/>
<property name="jobDataAsMap">
<map>
<entry key="numArr" value="10,20,30"/>
</map>
</property>
</bean>
I have a quartz job defined that runs this at 1:30am. The problem is this array definition does not work
<entry key="numArr" value="10,20,30"/>
We had to use list instead. Since the beans do not get initialized until the quartz job kicks in and it's unlikely we would be coding at 1:30am, we cannot catch this error locally. The only way right now is to change the quartz job's running time to force it to happen. We want to force these beans to be initialized on startup when we are running on local dev. Is there a way to do this?
If possible I would decouple your bean from the Quartz job. You could then intialise your bean separately in your spring configuration and it does not need to be made aware of Quartz. I would then use the spring MethodInvokingJobDetailFactoryBean to call a method on your decoupled object.
For example something similar to this:
<bean id="myBean class="...">
<property name="numArr" value="10,20,30"/>
</bean>
<bean id="myJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myBean" />
<property name="targetMethod" value="doSomething" />
</bean>
<bean id="staleTraderRatesTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="myJob" />
<property name="cronExpression" value="0 30 1 * * ?" />
</bean>