Apache Camel quartz2不会应用更改的cron表达式

时间:2014-07-18 12:45:03

标签: java apache-camel

我正在尝试使用JDBCJobStore在集群模式下使用camel-quartz2组件。

quartz.properties 档案:

org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=JobCluster

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.dataSource=dsQuartzTest

org.quartz.jobStore.isClustered=true

org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=5
org.quartz.dataSource.dsQuartzTest.driver = oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.dsQuartzTest.URL = jdbc:oracle:thin:pmuser@//10.13.13.10:1521/PDB1
org.quartz.dataSource.dsQuartzTest.user = pmuser
org.quartz.dataSource.dsQuartzTest.password = oracle
org.quartz.dataSource.dsQuartzTest.maxConnections = 10

camel-context.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring
       http://camel.apache.org/schema/spring/camel-spring.xsd">

    <bean id="quartz2" class="org.apache.camel.component.quartz2.QuartzComponent">
        <property name="propertiesFile" value="quartz.properties"/>
    </bean>

    <bean id="quartzBean" class="com.ubs.rbs.integration.QuartzBean"/>

    <camel:camelContext xmlns="http://camel.apache.org/schema/spring">

        <camel:route id="quartzRoute">
            <camel:from uri="quartz2://tictac?cron=0+0/5+*+1/1+*+?+*"/>
            <camel:setBody>
                <camel:simple>
                    ${header.triggerName} - ${header.fireTime}
                </camel:simple>
            </camel:setBody>
            <camel:to uri="log:hello"/>
        </camel:route>

<!--
        <camel:route>
            <camel:from uri="timer://updateQuartzRoute?repeatCount=1"/>
            <camel:to uri="bean:quartzBean?method=reschedule(*,'quartzRoute')"/>
        </camel:route>
-->

    </camel:camelContext>

</beans>

当我第一次启动应用程序时,camel-quartz2组件使用适当的cron表达式调度作业,所有工作都正常。但是,当我停止应用程序的所有实例时,触发器仍然处于WAITING状态(对于集群来说可能是好的,因为组件无法判断最后一个实例何时停止,同样,我无法判断这一点是否相关,但没有集群它似乎没有问题)。因此,当我下次启动应用程序时,触发器已经存在且其设置将不适用。重要的是,当我更改cron表达式并重新启动所有实例时,quartz使用DB中的旧表达式,而不是组件的uri中的新表达式。

我找到了解决此问题的方法,使用其他路由(在上面的xml中注释掉)来重新安排自定义bean中的quartz,如下所示:

public class QuartzBean {

    public void reschedule(CamelContext context, String quartzRouteId) throws Exception {
        QuartzEndpoint endpoint = (QuartzEndpoint) context.getRoute(quartzRouteId).getEndpoint();
        QuartzComponent component = endpoint.getComponent();
        Scheduler scheduler = component.getScheduler();

        Trigger oldTrigger = scheduler.getTrigger(endpoint.getTriggerKey());
        TriggerBuilder tb = oldTrigger.getTriggerBuilder();

        Trigger newTrigger = tb.withSchedule(CronScheduleBuilder.cronSchedule(endpoint.getCron())).build();

        scheduler.rescheduleJob(oldTrigger.getKey(), newTrigger);
    }
}

或者,我可以修改camel-quartz2组件,如下所示(org.apache.camel.component.quartz2.QuartzEndpoint#addJobInScheduler):

private void addJobInScheduler() throws Exception {
    // Add or use existing trigger to/from scheduler
    Scheduler scheduler = getComponent().getScheduler();
    JobDetail jobDetail;
    boolean triggerExisted = scheduler.getTrigger(triggerKey) != null;
    if (triggerExisted) {
        ensureNoDupTriggerKey();
    }

    jobDetail = createJobDetail();
    Trigger trigger = createTrigger(jobDetail);

    updateJobDataMap(jobDetail);

    // Schedule it now. Remember that scheduler might not be started it, but we can schedule now.
    Date nextFireDate = triggerExisted ? scheduler.rescheduleJob(triggerKey, trigger) : scheduler.scheduleJob(jobDetail, trigger);
    if (LOG.isInfoEnabled()) {
        LOG.info("Job {} (triggerType={}, jobClass={}) is scheduled. Next fire date is {}",
                 new Object[] {trigger.getKey(), trigger.getClass().getSimpleName(),
                               jobDetail.getJobClass().getSimpleName(), nextFireDate});
    }

    // Increase camel job count for this endpoint
    AtomicInteger number = (AtomicInteger) scheduler.getContext().get(QuartzConstants.QUARTZ_CAMEL_JOBS_COUNT);
    if (number != null) {
        number.incrementAndGet();
    }

    jobAdded.set(true);
}

与项目存储库中的当前版本不同,如果触发器已经存在,我的版本总是会创建新的触发器并重新安排作业。

我的问题是:我错过了一些明显的东西吗?这个组件应该如何在这种情况下工作?我是否应该尝试更改组件本身,还是有更好的方法从外部更改其计划?

UPD:我从maven尝试了2.13.1版本,从源代码尝试了2.14.SNAPSHOT。

2 个答案:

答案 0 :(得分:0)

Camel版本2.12.2及之前已知与Quartz相关的错误。如果不是,请给2.12.3及以上尝试。

答案 1 :(得分:0)

我已经提交了一个错误:https://issues.apache.org/jira/browse/CAMEL-7627以及补丁和单元测试。