web-dev-qa-db-fra.com

Utilisation de @Scheduled et @EnableScheduling mais donne NoSuchBeanDefinitionException

J'ai suivi exemples très simples en ligne pour configurer un travail cron au printemps, mais je continue à obtenir cette erreur dans mon journal de démarrage Tomcat à chaque fois:

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

Et les 2 classes Java utilisées pour implémenter le cron:

1) La classe @Configuration:

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

et classe d'emplois 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");
    }
}

En remarque, le travail cron s'exécute à minuit, mais il semble également s'exécuter de manière aléatoire à d'autres moments. Je ne sais pas s'il s'agit d'un bogue ou si mon expression cron est incorrecte: @Scheduled(cron = "0 0 * * * *")

Ma principale préoccupation en ce moment est la suivante: pourquoi ai-je des erreurs ScheduledAnnotationBeanPostProcessor? Il recherche un TaskScheduler et ScheduledExectorService. J'ai juste besoin de lancer ceci une fois par jour. Je ne fais aucun traitement simultané ou lorsque j'ai besoin de plusieurs threads. En fin de compte, ces erreurs sont-elles nuisibles OR dois-je les corriger?

23
logixplayer

selon l'exception Info "Impossible de trouver le bean TaskScheduler par défaut", la configuration doit définir "TaskScheduler" plutôt que "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();
   }

}

18
randy

EDIT: la meilleure réponse est ici et cela implique de créer un exécuteur:

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

PRÉCÉDENT (toujours valide cependant):

L'exception NoSuchBeanDefinitionException est enregistrée avec une gravité DEBUG et peut être ignorée en toute sécurité. Si vous regardez le code source de ScheduledAnnotationBeanPostProcessor, vous voyez qu'il essaie d'abord d'obtenir un TaskScheduler, puis un ScheduledExecutorService, puis il continue à "retomber dans le planificateur par défaut":

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

Vous pouvez supprimer l'exception en définissant au moins une gravité INFO sur org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor, comme

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

lors de l'utilisation de la déconnexion.

L'expression cron a six champs:

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

La syntaxe se trouve dans le quartz docs . Je ne suis pas sûr du "?" car, bien que la page indique

Le '?' est autorisé pour les champs jour du mois et jour de la semaine. Il est utilisé pour spécifier "aucune valeur spécifique". Ceci est utile lorsque vous devez spécifier quelque chose dans l'un des deux champs, mais pas dans l'autre.

les exemples sur cette page utilisent réellement? même lorsque l'autre champ est *. À mon humble avis, tous devraient fonctionner avec seulement *, afin d'exécuter tous les minuit, l'expression doit être

0 0 0 * * *
16
xtian

Pour résoudre ce problème, créez simplement le bean du planificateur de tâches dans config.

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

Avec Spring Boot 2.0.5, je continue à obtenir:

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

La seule façon de s'en débarrasser semble être d'utiliser l'interface SchedulingConfigurer dans votre @Configuration classe comme celle-ci:

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

Remarque: cela provient de https://www.callicoder.com/spring-boot-task-scheduling-with-scheduled-annotation/

3
Wim Deblauwe

Je suis d'accord que vous pouvez l'ignorer, mais le simple fait de changer la gravité ne le résoudra pas. J'ai eu le même problème mais j'utilise xml au lieu d'annotations, et dans mon cas, cela s'est produit parce que je n'ai pas inclus l'exécuteur dans ma définition de bean. Donc, l'ajout de cela l'a corrigé:

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

J'espère que ça aide.

Cordialement.

3
Eduardo G