[Logo] Terracotta Discussion Forums (LEGACY READ-ONLY ARCHIVE)
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
[Expert]
Quartz/Spring transaction weirdness  XML
Forum Index -> Quartz
Author Message
whosrod

neo

Joined: 07/19/2010 16:25:42
Messages: 1
Offline

I'm experiencing some strange issues related to Quartz and Spring transactions. I'm using SchedulerFactoryBean with a local PostgreSQL database. The problem is that immediate jobs aren't firing immediately when the scheduleJob() call is in a larger Spring transaction.

For example, the following code executes the job immediately:
Code:
 JobDetail jobDetail = new JobDetail("testping", PingJob.class);
 Trigger trigger = new SimpleTrigger("testping", new Date());
 jobScheduler.scheduleJob(jobDetail, trigger);
 


This code, however, delays the job execution for a few seconds (max of 30 seconds):
Code:
 DefaultTransactionDefinition def = new DefaultTransactionDefinition();
 TransactionStatus status = txManager.getTransaction(def);
 try {
 	JobDetail jobDetail = new JobDetail("testping", PingJob.class);
 	Trigger trigger = new SimpleTrigger("testping", new Date());
 	jobScheduler.scheduleJob(jobDetail, trigger);
 	txManager.commit(status);
 } catch (Exception e) {
 	txManager.rollback(status);
 }
 


This page "http://www.quartz-scheduler.org/docs/configuration/ConfigMain.html" showed me how to modify the delay in fire time via "org.quartz.scheduler.idleWaitTime", but that incurs a performance cost on my app. That page also mentions that that property shouldn't have to be modified unless XA transactions are being used, which I don't believe my app is using (local database).

So what am I doing wrong? Any help or insight would be most appreciated :)

Scheduler bean:
Code:
 <bean id="jobScheduler"
 		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
 		<property name="dataSource" ref="dataSource" />
 		<property name="transactionManager" ref="transactionManager" />
 		<property name="quartzProperties">
 			<value>
 				org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
 				org.quartz.jobStore.tablePrefix = QRTZ_
 			</value>
 		</property>
 		<property name="jobFactory">
 			<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
 		</property>
 		<property name="schedulerContextAsMap">
 			<map>
 			    <entry key="dataSource" value-ref="dataSource" />
 				<entry key="jobDao" value-ref="jobDao" />
 				<entry key="transactionManager" value-ref="transactionManager" />
 			</map>
 		</property>
 	</bean>
 


DB bean:
Code:
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
 		<property name="driverClassName" value="org.postgresql.Driver" />
 		<property name="url" value="jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}" />
 		<property name="username" value="${DB_USER}" />
 		<property name="password" value="${DB_PASS}" />
 		<property name="defaultAutoCommit" value="true" />
 		<property name="maxIdle" value="1" />
 	</bean>
 


TxManager bean:
Code:
 	<bean id="transactionManager"
 		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 		<property name="dataSource" ref="dataSource" />
 	</bean>
gyan10

ophanim

Joined: 06/28/2011 23:15:25
Messages: 701
Offline

This is an old thread and no update from a long time.Please let us know if you are still facing same issue.
Thanks

Gyan Awasthi
Terracotta -A Software AG company
iamgrief

neo

Joined: 04/27/2015 14:23:27
Messages: 1
Offline

Yes, this is some kind of necroposting but I faced exactly the same issue today and spend a lot of time searching for the root cause. I found one, I cannot guarantee that you were experiencing the same, but still.

Anyway, the idea is pretty simple. I found the following code in org.quartz.core.QuartzScheduler:
Code:
     public Date scheduleJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException {
         ...
         resources.getJobStore().storeJobAndTrigger(jobDetail, trig);
         notifySchedulerListenersJobAdded(jobDetail);
         notifySchedulerThread(trigger.getNextFireTime().getTime());
         notifySchedulerListenersSchduled(trigger);
 
         return ft;
     }
 

In case of database jobstore, the record should appear in the quartz_triggerz db table right after storeJobAndTrigger() being called.
So I set a breakpoint on the first notify and found that this is not true. The record appears later which means that the database transaction is not completed. That was the root cause in my case. I found a @Transactional annotation somewhere in the call chain. So the inner transaction created by jobStore was attached to the outer one and nobody from listeners and threads could get the data from the db when they were notified.

I would like to share the configuration of the quartz scheduler with the community, it works for me on latest versions of all dependent libraries:
Code:
            <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                 <property name="schedulerName" value="some_name"/> <!-- important to set, otherwise it will contain standard Object.toString() result with @ADDRESS part which will lead to inability to load jobs from the database between restarts since addresses change every time but the name is used to find jobs related to the current instance of scheduler -->
                 <property name="dataSource" ref="dataSource"/>
                 <property name="transactionManager" ref="transactionManager"/>
                 <property name="waitForJobsToCompleteOnShutdown" value="true"/> <!-- you might want another behavior -->
                 <property name="jobFactory">
                     <bean class="AutowiringSpringBeanJobFactory"/> <!-- this just handles @Autowired annotation for jobs with the help of AutowireCapableBeanFactory, I took it from https://gist.github.com/jeffsheets/5862630 -->
                 </property>
                 <property name="quartzProperties">
                     <map>
                         <entry key="org.quartz.jobStore.driverDelegateClass" value="org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"/> <!-- for correct work with lobs -->
                     </map>
                 </property>
             </bean>
         </property>
 


You can use PGSimpleDataSource, PGPoolingDataSource, I used c3p0.ComboPooledDataSource with PGSimpleDataSource passed inside.
 
Forum Index -> Quartz
Go to:   
Powered by JForum 2.1.7 © JForum Team