How to enable TaskScheduler in spring-boot?
Asked Answered
O

1

8

I'm using spring-boot to set up spring defaults. I'd like to use the @EnableScheduling mechanism, and schedule my tasks conditional.

Therefore I have to implement SchedulingConfigurer and set TaskScheduler explicit.

But when injecting the TaskScheduler, I get the following error. But why doesn't spring-boot automatically provide a Scheduler accordingly?

@Configuration
@EnableAutoConfiguration
@EnableScheduling
public class AppConfig {

}

@Service
public class JobService implements SchedulingConfigurer {
    @Autowired
    private TaskScheduler taskScheduler;

    //schedule the task dynamically
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler); //fails
        taskRegistrar.addTriggerTask(task, trigger);
    }
}

Error:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.scheduling.TaskScheduler; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.scheduling.TaskScheduler] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 15 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.scheduling.TaskScheduler] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 17 more
Overcapitalize answered 11/2, 2015 at 10:49 Comment(3)
Have you try to setup scheduler via xml config? As for me I have some problems with annotation driven configuration way, but it goes smooth with xml config.Vinegar
Because it doesn't. Not everyone needs a scheduler and detecting isn't really possible. So you wil have to add your own.Cassilda
Also it is a bit strange that your SchedulingConfigurer is a service, would be more logical to be a @Configuration class.Cassilda
C
9

You don't need to set a scheduler on the ScheduledTaskRegistrar. If one hasn't been configured it defaults to a ConcurrentTaskScheduler that wraps a single-threaded scheduled executor:

if (this.taskScheduler == null) {
    this.localExecutor = Executors.newSingleThreadScheduledExecutor();
    this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}

If you're happy with this default scheduler you can remove your autowiring of TaskScheduler and the call to set it on the ScheduledTaskRegistrar. Also, as Marten's suggested in the comments, you should make your SchedulingConfigurer a configuration class rather than a service.

These changes leave your code looking something like this:

@Configuration
static class TaskConfiguration implements SchedulingConfigurer {

    //schedule the task dynamically
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(task, trigger);
    }
}
Coss answered 11/2, 2015 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.