永远不会在DelayHandler上调用onApplicationEvent()

时间:2016-03-04 17:25:52

标签: spring-integration

我在@Configuration类中使用Spring Boot和Spring Integration Java DSL。其中一个流程是使用带有MessageStore的DelayHandler,通过.delay(String groupId,String expression,Consumer endpointConfigurer):

@Bean
public IntegrationFlow errorFlow() {
    return IntegrationFlows.from(errorChannel())
            ...
            .delay(...)
            ...
            .get();
}

我希望利用DelayHandler的reschedulePersistedMessages()功能,但我发现调用它的onApplicationEvent(ContextRefreshedEvent事件)实际上从未被调用过(?)

我不确定,但我怀疑这是因为DelayHandler未注册为Bean,因此AbstractApplicationContext中的registerListeners()无法自动注册DelayHandler(并通过注册非Bean侦听器) ApplicationHventMulticaster.addApplicationListener(ApplicationListener侦听器)没有为DelayHandler完成。

目前,我正在使用一种相当丑陋的解决方法来注册我自己的侦听器Bean,我将注入集成流Bean,然后在找到DelayHandler后手动调用onApplicationEvent():

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    Set<Object> integrationComponents = errorFlow.getIntegrationComponents();
    for (Object component : integrationComponents) {
        if (component instanceof DelayerEndpointSpec) {
            Tuple2<ConsumerEndpointFactoryBean, DelayHandler> tuple2 = ((DelayerEndpointSpec) component).get();
            tuple2.getT2().onApplicationEvent(event);
            return;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

嗯,是的。该测试用例证实了这个问题:

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class DelayerTests {

    private static MessageGroupStore messageGroupStore = new SimpleMessageStore();

    private static String GROUP_ID = "testGroup";

    @BeforeClass
    public static void setup() {
        messageGroupStore.addMessageToGroup(GROUP_ID, new GenericMessage<>("foo"));
    }

    @Autowired
    private PollableChannel results;

    @Test
    public void testDelayRescheduling() {
        Message<?> receive = this.results.receive(10000);
        assertNotNull(receive);
        assertEquals("foo", receive.getPayload());
        assertEquals(1, messageGroupStore.getMessageGroupCount());
        assertEquals(0, messageGroupStore.getMessageCountForAllMessageGroups());
    }

    @Configuration
    @EnableIntegration
    public static class ContextConfiguration {

        @Bean
        public IntegrationFlow delayFlow() {
            return flow ->
                      flow.delay(GROUP_ID, (String) null,
                        e -> e.messageStore(messageGroupStore)
                                .id("delayer"))
                        .channel(c -> c.queue("results"));
        }

    }

}

我们走了:documentation here

作为解决方法,我们可以在@Configuration

中执行此操作
@Autowired
private ApplicationEventMulticaster multicaster;

@PostConstruct
public void setup() {
    this.multicaster.addApplicationListenerBean("delayer.handler");
}

注意beanName进行注册。这正是我们的流定义中的.id("delayer")加上.handler bean定义的DelayHandler后缀。