Closed
Description
The way that @EnableScheduling
works can be surprising for users. The problem is that it uses bean lookup by type for TaskScheduler
(and TaskExecutor
) by default, and if the context contains more than one there is no strategy to fall back to a safe place (e.g. a well-known bean name). Thus this app blows up in your face when Spring Integration is on the classpath:
@SpringBootApplication
public class DemoApplication {
private static Log logger = LogFactory.getLog(DemoApplication.class);
@Scheduled(fixedDelay=2000)
public void work() {
logger.info("Hello");
}
@Bean
public TaskScheduler myTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
...
}
whereas this one is fine:
@SpringBootApplication
public class DemoApplication {
private static Log logger = LogFactory.getLog(DemoApplication.class);
@Scheduled(fixedDelay=2000)
public void work() {
logger.info("Hello");
}
...
}
Spring Integration exacerbates the problem, but actually what they do is pretty sensible (look for a bean with a well known name "taskScheduler" and use that if there is a conflict).
Corollary: the app works if the @Bean
is called "taskScheduler" as well:
@SpringBootApplication
public class DemoApplication {
private static Log logger = LogFactory.getLog(DemoApplication.class);
@Scheduled(fixedDelay=2000)
public void work() {
logger.info("Hello");
}
@Bean
public TaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler();
}
...
}