3

I am using Spring Integration to read files from a directory using following configuration. However I am looking to stop poller once I found any file until service not restarted again. Is there any way I can change poller delay at runtime OR start/stop Poller at runtime?

@Bean
public MessageChannel fileInputChannel() {
    return new DirectChannel();
}

@Bean
@InboundChannelAdapter(channel = "fileInputChannel", poller = @Poller(cron = "0 0/10 19-23,0-6 ? * *", maxMessagesPerPoll = "1"))
public MessageSource<File> fileReadingMessageSource() {
    FileReadingMessageSource source = new FileReadingMessageSource();
    File directory = new File(localFtpDirectory);
    if (clearLocalDir && directory.isDirectory() && directory.exists()) {
        LOG.info("Clear directory {} on startup of service", directory);
        Arrays.stream(directory.listFiles()).forEach(File::delete);
    }
    source.setDirectory(directory);
    source.setFilter(new LastModifiedFileFilter(remoteFileFilter));
    return source;
}

@Bean
@ServiceActivator(inputChannel = "fileInputChannel")
public MessageHandler fileHandler() {
    return new MessageHandlerService();
}
Sushil
  • 327
  • 1
  • 3
  • 20

2 Answers2

1

There is this annotation to use alongside with the @InboundChannelAdapter:

/**
 * When used alongside an EIP annotation (and no {@code @Bean}), specifies the bean name of
 * the consumer bean with the handler bean being {@code id.handler} (for a consuming
 * endpoint) or {@code id.source} for a message source (e.g. inbound channel adapter).
 * <p>
 * When there is also a {@code @Bean} annotation, this is the name of the consumer or
 * source polling bean (the handler or source gets the normal {@code @Bean} name). When
 * using on a {@code MessageHandler @Bean}, it is recommended to name the bean
 * {@code foo.handler} when using {@code @EndpointId("foo"}. This will align with
 * conventions in the framework. Similarly, for a message source, use
 * {@code @Bean("bar.source"} and {@code @EndpointId("bar")}.
 * <p>
 * <b>This is not allowed if there are multiple EIP annotations on the same method.</b>
 *
 * @author Gary Russell
 *
 * @since 5.0.4
 */
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EndpointId {

and there is a Cotrol Bus EIP implementation: https://docs.spring.io/spring-integration/docs/5.0.7.RELEASE/reference/html/system-management-chapter.html#control-bus.

With that you can send start()/stop() command messages whenever it is convenient for you.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
1

I had similar requirement, but was not satisfied with the accepted answer. The start/stop functionality mentioned here is defined by the Lifecycle/SmartLifecycle contract, and the typical scenario I can see is application shutdown or application context refresh. Simply, when I naively tried to use this I indeed got into problems very quickly.

My requirement was rather to pause the poller and resume it later on. This can be easily achieved by the advice and is very easy to implement. However, getting this knowledge was not easy and I ended up with framework source code investigation (indeed I might have overlooked something in the doc).

    @Bean
    public MessagePollingControlAdvice messagePollingControlAdvice() {
        return new MessagePollingControlAdvice();
    }

    //call this method for your DSL bridge configuration etc..
    Consumer<GenericEndpointSpec<BridgeHandler>> pollerConfiguration() {
        return b -> b.poller(pollerFactory -> pollerFactory.advice(messagePollingControlAdvice()));
    }
   

   public static class MessagePollingControlAdvice implements ReceiveMessageAdvice {
    private volatile boolean pollingActive = false;

    @Override
    public boolean beforeReceive(Object source) {
        return pollingActive;
    }

    @Override
    public Message<?> afterReceive(Message<?> result, Object source) {
        return result;
    }

    public boolean isPollingActive() {
        return pollingActive;
    }

    //call this method from whatever place in your code to activate/deactivate poller
    public void setPollingActive(boolean pollingActive) {
        this.pollingActive = pollingActive;
    }
   }
jan b
  • 67
  • 1
  • 5