在Quartz中使用JobStoreCMT - 阻止自动提交

时间:2011-03-18 08:01:03

标签: java scheduled-tasks quartz-scheduler

我正在尝试使用以下代码在Quartz中使用JDBC作业存储:

DateTime dt = new DateTime().plusHours(2);

JobDetail jobDetail = new JobDetail(identifier, "group", TestJob.class);
SimpleTrigger trigger = new SimpleTrigger(identifier, dt.toDate());

trigger.setJobName(identifier);
trigger.setJobGroup("group");

quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);

我正在按如下方式配置调度程序:

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
<property name="autoStartup" value="true" />
<property name="waitForJobsToCompleteOnShutdown" value="false" />
<property name="dataSource" ref="schedulerDataSource" />
<property name="nonTransactionalDataSource" ref="nonTXdataSource" />
<property name="quartzProperties">
    <props>
        <!--Job Store -->
        <prop key="org.quartz.jobStore.driverDelegateClass">
            org.quartz.impl.jdbcjobstore.StdJDBCDelegate
        </prop>

        <prop key="org.quartz.jobStore.class">
            org.quartz.impl.jdbcjobstore.JobStoreCMT
        </prop>
        <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
    </props>
</property>
</bean>

schedulerDataSource是标准的JNDI数据源,nonTXdataSource是通过简单的org.springframework.jdbc.datasource.DriverManagerDataSource配置的,我已将作业商店类指定为:o rg.quartz.impl.jdbcjobstore.JobStoreCMT并且是希望代码:

quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);
调用每个方法时,

不会将作业提交到数据库。基本上当我调用addJob时,作业会立即保存到数据库中,scheduleJob方法也会使触发器信息立即保存在数据库中,但这往往会在两个单独的事务中发生。

代码中有一些后续逻辑需要与一个事务中的预定作业一起提交到数据库,但无论我尝试什么,调度程序都会立即将作业提交到数据库他们的方法被称为。我在各种环境中尝试过Testing / Tomcat / Glassfish和各种数据源配置,但无济于事。

有人能指出我出错的方向吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

考虑到这一点,现在我相信你可以实现这一点,提供你自己的包裹DataSource,但你不应该这样做。我认为Quartz在内存中维护了一些必须与数据库同步的内部状态(或者至少它可以这样做)。如果您回滚事务或以其他方式修改数据库状态而不向Quartz通知此事实,则可能无法按预期工作。

另一方面,您可以使用Quartz暂停作业来实现类似的效果:您只需创建新作业并在添加任何触发器之前暂停它。然后,只有在提交事务后才能恢复它。

----------------------我原来的答案----------------------

我想,但是我不确定,也没试过,你可以尝试以下方法:

您需要围绕在内部使用DataSource.getConnection的代码进行事务处理。要实现这一点,您必须使用能够了解全局事务状态的数据源。我想JBoss应用服务器就是这样(即使使用普通的数据源)。

JBoss带有一个事务管理器(Arjuna)和数据源包装器(JBoss app server internal),它们至少知道全局事务状态。

其他选项包括Atomikos和XA数据源,但我的经验较少。

编辑:如果Quartz在内部使用明确的COMMITsetAutocommit(true),那么我的建议都无效。

答案 1 :(得分:0)

当你在SchedulerFactoryBean上设置数据源时,spring使用下面的类作为JobStore(Quartz的JobStoreCMT的扩展)

LocalDataSourceJobStore 这支持事务性和非事务性DataSource访问。

请尝试以下

  1. 删除属性org.quartz.jobStore.class [编辑:忽略,反正]

  2. 确保addJob / ScheduleJob的方法在spring管理事务中。