Using @Scheduled and @EnableScheduling but gives NoSuchBeanDefinitionException

55,608

Solution 1

according to exception Info Could not find default TaskScheduler bean, the config should define TaskScheduler rather than "Executor"

@Configuration
public class AppContext extends WebMvcConfigurationSupport {
    @Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }

    // Of course , you can define the Executor too
    @Bean
    public Executor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
   }
}

Solution 2

EDIT: the best answer is here and it involves creating an Executor:

@Configuration
@EnableAsync
public class AppContext extends WebMvcConfigurationSupport {
    @Bean
    public Executor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
    }
}

PREVIOUS (still valid though):

The NoSuchBeanDefinitionException is logged with a DEBUG severity and can be safely ignored. If you look at the source code for ScheduledAnnotationBeanPostProcessor, you see that it first tries to get a TaskScheduler, then a ScheduledExecutorService, then it keeps going on "falling back to default scheduler":

    if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
        Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
        try {
            // Search for TaskScheduler bean...
            this.registrar.setScheduler(this.beanFactory.getBean(TaskScheduler.class));
        }
        catch (NoUniqueBeanDefinitionException ex) {
            throw new IllegalStateException("More than one TaskScheduler exists within the context. " +
                    "Remove all but one of the beans; or implement the SchedulingConfigurer interface and call " +
                    "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback.", ex);
        }
        catch (NoSuchBeanDefinitionException ex) {
            logger.debug("Could not find default TaskScheduler bean", ex);
            // Search for ScheduledExecutorService bean next...
            try {
                this.registrar.setScheduler(this.beanFactory.getBean(ScheduledExecutorService.class));
            }
            catch (NoUniqueBeanDefinitionException ex2) {
                throw new IllegalStateException("More than one ScheduledExecutorService exists within the context. " +
                        "Remove all but one of the beans; or implement the SchedulingConfigurer interface and call " +
                        "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback.", ex);
            }
            catch (NoSuchBeanDefinitionException ex2) {
                logger.debug("Could not find default ScheduledExecutorService bean", ex);
                // Giving up -> falling back to default scheduler within the registrar...
            }
        }
    }

You can remove the exception by setting at least a INFO severity on org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor, like

<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>

when using logback.

The cron expression has six fields:

second (0-59), minute (0-59), hour (0-23, 0 = midnight), day (1-31), month (1-12), weekday (1-7, 1 = Sunday)

The syntax can be found in the quartz docs. I'm not sure about the "?" character because, although the page says

The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify “no specific value”. This is useful when you need to specify something in one of the two fields, but not the other.

the examples on that page actually use ? even when the other field is *. IMHO all should work with just *, so in order to execute every midnight, the expression should be

0 0 0 * * *

Solution 3

For solving this problem just create task scheduler bean in config.

@Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }

Solution 4

With Spring Boot 2.0.5, I keep getting:

2018-11-20 11:35:48.046  INFO 64418 --- [  restartedMain] s.a.ScheduledAnnotationBeanPostProcessor : 
No TaskScheduler/ScheduledExecutorService bean found for scheduled processing

The only way to get rid of it seems to be using SchedulingConfigurer interface in your @Configuration class like this:

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
    private final int POOL_SIZE = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();

        threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
        threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
        threadPoolTaskScheduler.initialize();

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

Note: This was taken from https://www.callicoder.com/spring-boot-task-scheduling-with-scheduled-annotation/

Solution 5

I agree you can ignore it but just changing the severity will not fix it. I had the same issue but I am using xml instead of annotations, and in my case it happened because I did not included the executor on my bean definition. So adding this fixed it:

<task:annotation-driven executor="myExecutor"
    scheduler="myScheduler" />
<task:executor id="myExecutor" pool-size="5" />
<task:scheduler id="myScheduler" pool-size="10" />

I hope it helps.

Regards.

Share:
55,608
logixplayer
Author by

logixplayer

Updated on December 24, 2020

Comments

  • logixplayer
    logixplayer over 3 years

    I have followed very simple examples online to set up a cron job in Spring yet I keep getting this error in my Tomcat startup log each and every time:

    2015-05-25 00:32:58 DEBUG ScheduledAnnotationBeanPostProcessor:191 - 
    Could not find default TaskScheduler bean org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
    qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined
    
    2015-05-25 00:32:58 DEBUG ScheduledAnnotationBeanPostProcessor:202 - Could not    
    find default ScheduledExecutorService bean
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying    
    bean of type [org.springframework.scheduling.TaskScheduler] is defined
    

    And the 2 java classes used to implement the cron:

    • The @Configuration class:

      @Configuration
      @EnableScheduling
      public class ClearTokenStoreCronEnable {    
        final static Logger log =   
        LoggerFactory.getLogger(ClearTokenStoreCronEnable.class);
        private @Autowired TokenStoreRepository tokenStoreRepository; 
      }
      
    • and Cron job class:

      @Service
      public class ClearTokenStoreWorkerService {
      
          final static Logger log = LoggerFactory.getLogger(ClearTokenStoreWorkerService.class);
          private @Autowired TokenStoreRepository tokenStoreRepository;
      
          //@Scheduled(fixedDelay=5000)
          //run daily at midnight
          @Scheduled(cron = "0 0 * * * *")
          public void tokenStoreTable() {
              log.debug("tokenstore table truncated - start");
              tokenStoreRepository.deleteAll();
              log.debug("tokenstore table truncated - end");
          }
      }
      

    As a side note, the cron job runs at midnight but it also seems to run randomly at other times. Not sure if this is a bug or my cron expression is wrong: @Scheduled(cron = "0 0 * * * *")

    My main concern at this time is why am I getting ScheduledAnnotationBeanPostProcessor errors? It's looking for a TaskScheduler and ScheduledExectorService. I just need to fire this once a day. I am not doing any concurrent processing or where I need multiple threads. Ultimately are these errors harmful OR do I need to fix them?