我有一个由cron表达式触发的spring整合流程,如下所示:
<int-ftp:inbound-channel-adapter id="my-input-endpoint" ...>
<int:poller trigger="my-trigger"/>
</int-ftp:inbound-channel-adapter>
<bean id="my-trigger"
class="org.springframework.scheduling.support.CronTrigger">
<constructor-arg value="0 * * * * *" />
</bean>
工作正常。但是现在我必须扩展实现以使其集群就绪(在同一时间点仅在一个集群节点上执行作业)。
我希望在集群模式下使用Quartz框架(在数据库中保持作业状态)来触发此集成流程。 Quartz提供了一个开箱即用的漂亮解决方案。唯一的问题是如何将Quartz与现有的inbout-channer-adapter集成? “poller”的“trigger”属性只接受org.springframework.scheduling.Trigger的子类。我找不到“poller trigger”和Quartz框架之间的任何桥梁。
提前多多感谢!
答案 0 :(得分:7)
这是一种方式......
将入站适配器上的自动启动属性设置为false。
创建一个只触发一次的自定义触发器......
public static class FireOnceTrigger implements Trigger {
boolean done;
public Date nextExecutionTime(TriggerContext triggerContext) {
if (done) {
return null;
}
done = true;
return new Date();
}
public void reset() {
done = false;
}
}
在您的石英作业中,获取对触发器的引用和SourcePollingChannelAdapter
。
当石英触发器发射时,有石英作业
答案 1 :(得分:2)
来自Gary的解决方案。这是我的春天背景:
<int-ftp:inbound-channel-adapter id="my-endpoint"
auto-startup="false">
<int:poller trigger="my-endpoint-trigger"/>
</int-ftp:inbound-channel-adapter>
<bean id="my-endpoint-trigger" class="com.my.FireOnceTrigger"/>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="my-job-trigger" />
</list>
</property>
<property name="schedulerContextAsMap">
<map>
<entry key="inputEndpoint"><ref bean="my-input-endpoint" /></entry>
<entry key="inputEndpointTrigger"><ref bean="my-endpoint-trigger" /></entry>
</map>
</property>
</bean>
<bean id="my-job-trigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="cronExpression" value="0 * * * * ?" />
<property name="jobDetail" ref="my-job" />
</bean>
<bean name="my-job" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.my.MyActivatorJob " />
</bean>
和MyActivatorJob类:
public class MyActivatorJob extends QuartzJobBean implements {
private AbstractEndpoint inputEndpoint;
private FireOnceTrigger inputEndpointTrigger;
public void setInputEndpoint(final AbstractEndpoint pInputEndpoint) {
this.inputEndpoint = pInputEndpoint;
}
public void setInputEndpointTrigger(final FireOnceTrigger pInputEndpointTrigger) {
this.inputEndpointTrigger = pInputEndpointTrigger;
}
@Override
protected void executeInternal(final JobExecutionContext pParamJobExecutionContext)
throws JobExecutionException {
inputEndpoint.stop();
inputEndpointTrigger.reset();
inputEndpoint.start();
}
}
作为下一步,必须重构这个spring上下文,以便用更灵活的东西替换schedulerContextAsMap的用法,并能够定义更多的作业来激活和停用许多不同的端点。
感谢Gary到目前为止!
答案 2 :(得分:0)
尝试按照您的建议整合石英和弹簧,但遇到了另外两个问题:
1。)使用Quartz 2.x和Spring 3.x时出现IncompatibleClassChangeError异常。这是一个已知的问题,但我没有找到任何解决方案。
2.。)将其他spring bean注入Quarz作业实例。我找到了一些解决方案,但没有人适合我。我尝试了使用
的那个<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory">
<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
</property>
<property name="triggers">
...
</property>
<property name="schedulerContextAsMap">
<map>
<entry key="inputEndpoint" value-ref="my-endpoint" />
</map>
</property>
</bean>
将其他bean注入作业但是在将此属性添加到SchedulerFactoryBean后,作业未被执行(我没有看到任何异常)。删除属性“schedulerContextAsMap”会使作业再次运行。
答案 3 :(得分:0)
我还没有尝试过,但是看到Quartz 2和Spring兼容性问题似乎已在Spring 3.1.1中得到修复。见https://jira.springsource.org/browse/SPR-8889