Использование JobStoreCMT в Quartz - предотвращение автоматической фиксации - PullRequest
1 голос
/ 18 марта 2011

Я пытаюсь использовать JDBC Job Store в Кварце со следующим кодом:

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 вызывает немедленное сохранение информации о триггере в базе данных, но это обычно происходит уже через две отдельные транзакции.

В коде присутствует довольно много последующей логики, которую необходимо зафиксировать в базе данных вместе с запланированными заданиями в одной транзакции, однако, независимо от того, что я пробую, задания планируются в базу данных, как только они методы называются. Я пробовал в различных средах Тестирование / Tomcat / Glassfish и различные конфигурации источников данных, но безрезультатно.

Может ли кто-нибудь указать мне, куда я иду не так?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 22 марта 2011

Когда вы устанавливаете источник данных в SchedulerFactoryBean, Spring использует следующий класс как JobStore (расширение для JobStoreCMT в Quartz)

LocalDataSourceJobStore Это поддерживает как транзакционный, так и нетранзакционный доступ к источникам данных.

Пожалуйста, попробуйте следовать

  1. Удалить свойство org.quartz.jobStore.class [Редактировать: В любом случае его игнорируют]

  2. Убедитесь, что метод addJob / ScheduleJob находится в управляемой транзакции весной.

0 голосов
/ 20 марта 2011

Подумав немного, теперь я верю, что вы можете добиться этого, создав собственную упаковку DataSource, но вы не должны этого делать .Я думаю, что Quartz поддерживает некоторое внутреннее состояние в памяти, которое должно быть синхронизировано с базой данных (или, по крайней мере, это может быть так).Если вы откатите транзакцию или иным образом измените состояние базы данных, не уведомив об этом Quartz, она может работать не так, как ожидалось.

С другой стороны, вы можете использовать приостановку заданий Quartz для достижения аналогичного эффекта: вы просто создаетеновое задание и приостановите его перед добавлением любых триггеров.Затем вы возобновите его только после совершения транзакции.

---------------------- мой оригинальный ответ ----------------------

Я думаю, но я не уверен, не пробовал это, что вы можете попробовать следующее:

Вам нужнотранзакция вокруг кода, который использует DataSource.getConnection внутри.Чтобы достичь этого, вы должны использовать источник данных, который будет знать о состоянии глобальной транзакции.Я предполагаю, что сервер приложений JBoss дает вам именно это (даже с простым источником данных).

JBoss поставляется с менеджером транзакций (Arjuna) и оболочками источников данных (внутренний сервер приложений JBoss), которые, по крайней мере, осведомлены о глобальномсостояние транзакции.

Другие варианты включают Atomikos и источник данных XA, но у меня меньше опыта здесь.

Редактировать: если Quartz использует явные COMMIT или setAutocommit(true) внутренне, оба мои предложенияне будет работать.

...