8

我有一个由 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-adaptor 集成?“poller”的“trigger”属性只接受 org.springframework.scheduling.Trigger 的子类。我找不到“轮询触发器”和 Quartz 框架之间的任何桥梁。

提前谢谢了!

4

4 回答 4

8

这是一种方法...

将入站适配器上的自动启动属性设置为 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. 适配器.stop()
  2. 触发器.reset()
  3. 适配器.start()
于 2012-07-19T15:49:01.693 回答
2

加里的解决方案有效。这是我的春天背景:

<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 的使用,并能够定义更多激活和停用许多不同端点的作业。

到目前为止感谢加里!

于 2012-07-26T13:23:33.157 回答
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”会使作业再次运行。

于 2012-07-23T14:59:27.617 回答
0

我还没有尝试过,但看到 Quartz 2 和 Spring 的兼容性问题似乎已经在 Spring 3.1.1 中得到修复。见https://jira.springsource.org/browse/SPR-8889

于 2013-07-16T06:59:42.970 回答