具有弹簧集成的启动竞争条件弹簧批

时间:2016-12-14 14:33:45

标签: java spring-integration spring-batch

对于我使用弹簧启动,弹簧批量和弹簧集成的应用程序。

我的问题是,在启动时,当所有内容都自动配置并自动连线时,连接到RabbitMQ的spring-integration @MessageEndpoints开始处理其队列中的可用消息。根据收到的消息,这些@MessageEndpoints试图通过它自动连线的JobRegistery来启动特定的弹簧批处理作业。

由于所有自动配置,并非所有作业都已注册到使用过的JobRegistery! (几秒钟之后他们会)。

将所有弹出批处理作业注册到JobRegistery后,应启动@MessageEndpoints。这可能吗?也许以为ContextRefreshEvent?

2 个答案:

答案 0 :(得分:0)

我只看了代码,问题似乎是AutomaticJobRegistrar使用上下文刷新事件来加载作业;它应该真正实现SmartLifecycle并从“早期”阶段开始。

spring集成组件实现SmartLifecycle,入站端点(例如Rabbit端点)在后期开始。

我建议您打开批处理的JIRA - AutomaticJobRegistrar代码中有一个TODO:

// TODO: With Spring 3 a SmartLifecycle is started automatically

作为解决方法,您可以在入站适配器上将autoStartup设置为false,并使用您自己的事件侦听器在上下文刷新事件中启动它们。

听众应该实施Ordered; AutomaticJobRegistrarOrdered.LOWEST_PRECEDENCE,因此您希望以更高的优先级(较低优先级)运行。

答案 1 :(得分:0)

Gary Russell感谢你为正确的方向努力!我解决了它如下:

  1. 在集成XML中禁用入站通道的自动启动。
  2. 在SpringApplication.run()之后,如果手动启动这些入站通道,可以通过getBeansOftype()找到。
  3. public static void main(final String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringBatchApplication.class, args);
        startInboundChannelAdapters(context);
    }    
    private static void startInboundChannelAdapters(ConfigurableApplicationContext context) {
        Map<String, AmqpInboundChannelAdapter> adapters = context.getBeansOfType(AmqpInboundChannelAdapter.class);
        adapters.forEach((name, adapter) -> {
            if (!adapter.isRunning()) {
                adapter.start();
            }
        });
    }
    
相关问题