通过JMX调用集群Quartz的事务问题

时间:2014-01-10 10:05:35

标签: java spring quartz-scheduler

我设置Quartz 2.1.0以集群模式在Websphere中运行,使用JobStoreTX,我启用了org.quartz.scheduler.jmx.export,这样我就可以通过JMX访问quartz scheduler。

问题是当我想通过JMX调用某些方法时,我对sql做了一些异常:

java.lang.Exception: Failure obtaining db row lock: Not in transaction.
    at org.quartz.impl.jdbcjobstore.StdRowLockSemaphore.executeSQL(StdRowLockSemaphore.java:116)
    at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:115)
    at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:238)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.removeTrigger(JobStoreSupport.java:1410)
    at org.quartz.core.QuartzScheduler.unscheduleJob(QuartzScheduler.java:1026)
    at org.quartz.core.QuartzScheduler.deleteJob(QuartzScheduler.java:934)
    at org.quartz.core.QuartzSchedulerMBeanImpl.deleteJob(QuartzSchedulerMBeanImpl.java:352)

似乎调度程序中的所有操作都需要包含在事务中,但是当通过JMX调用时,不存在任何事务。我该如何解决?

<property name="quartzProperties">
            <props>
                <prop key="org.quartz.scheduler.instanceName">myApp</prop>
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
                <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
                <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
                <prop key="org.quartz.jobStore.tablePrefix">q</prop>
                <prop key="org.quartz.jobStore.isClustered">true</prop>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">5</prop>
                <prop key="org.quartz.threadPool.threadPriority">5</prop>
                <prop key="org.quartz.scheduler.skipUpdateCheck">true</prop>
                <prop key="org.quartz.scheduler.jmx.export">true</prop>
                <prop key="org.quartz.scheduler.jmx.objectName">quartz:type=QuartzScheduler,name=JmxScheduler</prop>
            </props>
        </property>

更新:

我正在使用spring,因此JobStoreTX被覆盖到LocalDataSourceJobStore

UPDATE2

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<jee:jndi-lookup id="dataSourceCron" jndi-name="jdbc/..." />



<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />
    <property name="dataSource" ref="dataSourceCron" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="overwriteExistingJobs" value="true" />
    <property name="autoStartup" value="true" />
    <property name="triggers" ref="jobTriggers" />
    <property name="jobDetails" ref="jobDetails" />
(properties)

</bean>

2 个答案:

答案 0 :(得分:0)

Spring事务管理器在通过应用程序启动的作业范围内处于活动状态,但是当通过JMX对同一作业进行攻击时,它不会处于活动状态。

您如何通过JMX注册可以发布的作业,您可以发布代码吗?

最好的方法是使用JMX Spring集成工具,可以通过JMX注册Spring bean,请参阅文档here。有here一个如何在JMX中发布Spring bean的例子。

答案 1 :(得分:0)

由于Quartz Scheduler是一个托管的spring bean,你可以使用spring declarative transaction management来识别Scheduler“事务”。

使QuartzSchedulerMBeanImpl“事务意识到”可能是一种更简洁的方法,但这有点棘手,因为它不是一个托管的spring bean。 (它创建了here)。通过注册&amp;自己暴露mbean,你可以使用spring的声明式事务管理来使其“知道事务”。另一种方法是使用AspectJ使mbean“知道事务”。