LocalDataSourceJobStore spring托管事务配置

时间:2014-09-25 11:06:01

标签: spring quartz-scheduler transactional

我遇到了将spring 4.x和quartz 2.2.1的配置用于进行事务操作的问题。

我正在使用的配置可以在下面找到:

<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
      p:jobFactory-ref="acquistionServiceJobFactory" p:dataSource-ref="dataSource"
      p:transactionManager-ref="transactionManager">
    <property name="triggers">
        <list>
            <ref bean="xxxJob"/>
            <ref bean="yyyJob"/>
        </list>
    </property>
    <property name="quartzProperties">
        <props>
            <prop key="org.quartz.scheduler.instanceName">${org.quartz.scheduler.instanceName}</prop>
            <prop key="org.quartz.scheduler.instanceId">${org.quartz.scheduler.instanceId}</prop>
            <prop key="org.quartz.scheduler.skipUpdateCheck">true</prop>
            <prop key="org.quartz.scheduler.jmx.export">${org.quartz.scheduler.jmx.export}</prop>
            <prop key="org.quartz.scheduler.jmx.objectName">${org.quartz.scheduler.jmx.objectName}</prop>

            <prop key="org.quartz.threadPool.class">${org.quartz.threadPool.class}</prop>
            <prop key="org.quartz.threadPool.threadCount">${org.quartz.threadPool.threadCount}</prop>
            <prop key="org.quartz.threadPool.threadPriority">${org.quartz.threadPool.threadPriority}</prop>
            <prop key="org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread">
                ${org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread}
            </prop>

            <prop key="org.quartz.jobStore.tablePrefix">${org.quartz.jobStore.tablePrefix}</prop>
            <prop key="org.quartz.jobStore.driverDelegateClass">${org.quartz.jobStore.driverDelegateClass}</prop>
            <prop key="org.quartz.jobStore.isClustered">${org.quartz.jobStore.isClustered}</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--  Quartz Scheduler Transaction Propagation -->
<tx:advice id="quartzSchedulerAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="get*" read-only="true" propagation="SUPPORTS" />
        <tx:method name="set*" read-only="true" propagation="SUPPORTS" />
        <tx:method name="is*" read-only="true" propagation="SUPPORTS" />
        <tx:method name="insert*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="update*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="delete*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="schedule*" read-only="false" propagation="REQUIRED" rollback-for="org.quartz.SchedulerException"/>
        <tx:method name="pause*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="resume*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="run*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="update*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="delete*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="toggle*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="clone*" read-only="false" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<tx:advice id="localDataSourceJobStoreAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" read-only="false" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="quartzSchedulerPointcut"
                  expression="execution(* org.quartz.core.QuartzScheduler.*(..))" />
    <aop:advisor advice-ref="quartzSchedulerAdvice" pointcut-ref="quartzSchedulerPointcut" />
</aop:config>

quartz.properties内容:

org.quartz.scheduler.instanceName=Quartz2Scheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.jmx.export=true
org.quartz.scheduler.jmx.objectName=Jobscheduelr:group=quartz,name=QuartzScheduler

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.isClustered=true

org.quartz.jobStore.tablePrefix = QRTZ2_

由于quartz在集群环境中运行,因此日志通常包含以下日志语句:

 No record found for selection of Trigger with key : ...

实际上链接到石英错误修正:https://jira.terracotta.org/jira/browse/QTZ-386

在我所面临的情况中,出现此问题的原因是LocalDataSourceJobStore上的操作不是事务性的。 我已经广泛搜索了一个示例项目,展示如何覆盖spring和amp;之间的事务方面。石英作业,但尚未找到覆盖它的样本。

我期待当我在石英作业的执行(JobExecutionContext)方法处于活动事务中时。

org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive() 

从类org.springframework.scheduling.quartz.SchedulerFactoryBean的javadoc中取出的片段:

 * The preferred way to achieve transactional execution is to demarcate
 * declarative transactions at the business facade level, which will
 * automatically apply to Scheduler operations performed within those scopes.
 * Alternatively, you may add transactional advice for the Scheduler itself.

另一方面,对于cron&amp;简单的作业,大多数操作都直接使用localDataSourceJobStore执行,而localDataSourceJobStore不是Spring容器的一部分,并且不会被事务AOP建议考虑在内。

从类org.springframework.scheduling.quartz.LocalDataSourceJobStore的javadoc取出的片段

* Operations performed by this JobStore will properly participate in any
* kind of Spring-managed transaction, as it uses Spring's DataSourceUtils
* connection handling methods that are aware of a current transaction.

显然似乎必须有一种方法在Spring事务中包含LocalDataSourceJobStore,但我似乎没有找到源自方法org.quartz.core.QuartzSchedulerThread#run()的调用 任何人都可以在这方面给我一些暗示吗?

0 个答案:

没有答案