Использование @Scheduled и @EnableScheduling, но дает исключение NoSuchBeanDefinitionException

Я выполнил очень простые примеры в Интернете, чтобы настроить задание cron в Spring, но я все время получаю эту ошибку в журнале запуска Tomcat каждый раз:

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

И два класса Java, используемые для реализации cron:

1) Класс @Configuration:

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

и класс работы Cron:

@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");
    }
}

Как побочная заметка, задание cron работает в полночь, но, похоже, оно также запускается случайным образом в другое время. Не уверен, что это ошибка, или мое выражение cron неверно: @Scheduled(cron = "0 0 * * * *")

Моя главная забота в это время - почему я получаю ошибки ScheduledAnnotationBeanPostProcessor? Он ищет TaskScheduler и ScheduledExectorService. Мне просто нужно запускать это один раз в день. Я не выполняю параллельную обработку или мне нужно несколько потоков. В конечном счете, эти ошибки вредны или мне нужно их исправить?

Ответы

Ответ 1

EDIT: лучший ответ здесь и предполагает создание Исполнителя:

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

ПРЕДЫДУЩИЙ (все еще действительный):

Исключение NoSuchBeanDefinitionException регистрируется с серьезностью DEBUG и может быть безопасно проигнорировано. Если вы посмотрите на исходный код ScheduledAnnotationBeanPostProcessor, вы увидите, что сначала он пытается получить TaskScheduler, затем ScheduledExecutorService, а затем продолжает "возвращаться к планировщику по умолчанию":

    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...
            }
        }
    }

Вы можете удалить исключение, установив хотя бы степень серьезности INFO на org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor, например

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

при использовании журнала.

Выражение cron имеет шесть полей:

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

Синтаксис можно найти в кварцевых документах. Я не уверен в "?" потому что, хотя на странице написано

"?" символ разрешен для полей дня месяца и дня недели. Он используется для указания "нет специального значения". Это полезно, когда вам нужно указать что-то в одном из двух полей, но не в другом.

примеры на этой странице на самом деле используются? даже если другое поле равно *. IMHO все должно работать только с *, поэтому для выполнения каждой полуночи выражение должно быть

0 0 0 * * *

Ответ 2

в соответствии с исключением Info "Не удалось найти Default TaskScheduler bean", config должен определить "TaskScheduler", а не "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();
   }

}

Ответ 3

Я согласен, что вы можете игнорировать его, но просто изменение серьезности не устранит его. У меня была такая же проблема, но я использую xml вместо аннотаций, и в моем случае это произошло потому, что я не включил исполнителя в мое определение bean. Поэтому добавление этого исправлено:

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

Надеюсь, это поможет.

С уважением.