[英]Apache Camel quartz2 doesn't apply changed cron expression
I'm trying to use camel-quartz2 component in a cluster mode with JDBCJobStore. 我正在尝试使用JDBCJobStore在集群模式下使用camel-quartz2组件。
quartz.properties file: 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 file: 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>
When I first start the application, camel-quartz2 component schedules job with appropriate cron expression, and all works just OK. 当我第一次启动应用程序时,camel-quartz2组件使用适当的cron表达式调度作业,并且一切正常。 But, when I stop all instances of app, trigger remains in a WAITING state (it's, probably, OK for cluster, as component cannot tell when last instance is stopped, also, I cannot tell if this point is relevant, but without cluster it seems was no issue). 但是,当我停止应用程序的所有实例时,触发器仍然处于WAITING状态(对于集群来说可能是好的,因为组件无法判断最后一个实例何时停止,同样,我无法判断这一点是否相关,但没有集群它似乎没有问题)。 So, when I start app next time trigger is already exists and its settings won't apply. 因此,当我下次启动应用程序时,触发器已经存在且其设置将不适用。 Importantly, when I change cron expression and restart all instances, quartz uses old expression from DB, not new one from component's uri. 重要的是,当我更改cron表达式并重新启动所有实例时,quartz使用DB中的旧表达式,而不是组件的uri中的新表达式。
I found a workaround for this issue, using additional route (commented out in the xml above) to reschedule quartz in the custom bean as below: 我找到了解决此问题的方法,使用其他路由(在上面的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);
}
}
Alternatively, I can patch camel-quartz2 component as below (org.apache.camel.component.quartz2.QuartzEndpoint#addJobInScheduler): 或者,我可以修改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);
}
Unlike the current version in the project's repository, my version always creates new trigger and reschedules job if trigger already existed. 与项目存储库中的当前版本不同,如果触发器已经存在,我的版本总是创建新的触发器和重新安排作业。
My questions are: Am I missing something obvious? 我的问题是:我错过了一些明显的东西吗? How this component supposed to work in such scenario? 这个组件应该如何在这种情况下工作? Should I try to change component itself or is there a better way to change its schedule from outside? 我应该尝试更改组件本身还是有更好的方法从外部更改其计划?
UPD: I tried versions 2.13.1 from maven and 2.14.SNAPSHOT from sources. UPD:我从maven尝试了2.13.1版本,从源代码尝试了2.14.SNAPSHOT。
Camel versions 2.12.2 and before have known bugs related to Quartz. Camel版本2.12.2和之前已知与Quartz相关的错误。 Give 2.12.3 and upwards a try, if you're not. 如果不是,请试试2.12.3及以上。
我提交了一个错误: https : //issues.apache.org/jira/browse/CAMEL-7627以及补丁和单元测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.