Spring Integration @Scheduled not working due to @Poller

Viewed 1183

I have a Spring Boot / Spring Integration application running that makes use of @Poller in Spring Integration and also @Scheduled on another method in a mostly-unrelated class. The @Poller is for polling an FTP server for new files. However I've found that it seems like the @Poller is somehow interfering with my @Scheduled method.

The @Poller has maxMessagesPerPoll = -1 so that it will process as many files as it can get. However, when I first start my application, there are over 100 files on the FTP server, so it's going to process them all. What I have found is that, if these files are being processed, then the @Scheduler stops triggering at all.

For example, if I set my @Scheduled to have a fixedDelay = 1 to trigger every millisecond and then start my application, the @Scheduled method will trigger a few times, until the @Poller triggers and begins processing messages, at which point my @Scheduled method completely stops triggering. I assumed that simply there was some task queue that was being filled by the @Poller so I simply needed to wait for all of the messages to be processed, but even after the @Poller is completely done and has processed all of the files, the @Scheduled method still does not trigger at all.

My thoughts are that maybe there is some task queue that is being filled by the @Poller, which is breaking my @Scheduled method, but if so, I still don't see any way that I can use a separate task queue for the different methods, or any other possible options for customizing or fixing this issue.

Does anyone have any idea what might be happening to my @Scheduled method, and how can I fix this?

@Poller:

    @Bean
    @InboundChannelAdapter(channel = "ftpChannel", poller = @Poller(cron = "0/5 * * ? * *", maxMessagesPerPoll = "-1"))
    public MessageSource<InputStream> myMessageSource() {
        //Build my message source
        return messageSource;
    }

@Scheduled:

@Scheduled(fixedDelay = 6000)
public void myScheduledMethod(){
  //Do Stuff
}
3 Answers

They do use the same bean name for their scheduler taskScheduler.

It should only be a problem if you have 10 or more pollers (the default scheduler bean configured by Spring Integration has a pool size of 10 by default). A common mistake is having many queue channels (which hold on to scheduler threads for a second at a time, by default).

If you only have one poller, and not a lot of queue channels, I can't explain why you would get thread starvation.

You can increase the pool size - see Configuring the Task Scheduler.

Or you can use a different scheduler in the ScheduledAnnotationBeanPostProcessor.

As already pointed out, the problem is linked to task schedulers having the same name, although it may occur even if there are fewer than 10 pollers. Spring Boot auto-configuration provides scheduler with default pool size of 1 and registration of this scheduler may happen before the registration of taskScheduler, provided by Spring Integration.

Configuring task scheduler via Spring Integration properties doesn't help as this bean doesn't get registered at all. But providing own instance of TaskScheduler with adjusted pool size, changing pool size of auto-configured scheduler via spring.task.scheduling.pool.size property or excluding TaskSchedulingAutoConfiguration should solve the issue.

In our case, the Poller was used by inbound-channel-adapter to access mail from the IMAP server - but when it polls for an email with large attachments, it blocks the thread used by @Scheduled as it only uses a single thread for scheduling the task. So we set the Spring property spring.task.scheduling.pool.size=2 - which now allows the @Scheduled method to run in a different thread even if the poller gets blocked (in a different thread) when trying to fetch mail from IMAP server

Related