111 votes

Comment activer ou désactiver de manière conditionnelle les tâches planifiées dans Spring ?

Je suis en train de définir des tâches planifiées avec des modèles de style cron dans Spring, en utilisant la fonction @Scheduled annotation.

Le modèle de cron est stocké dans un fichier de propriétés de configuration. En fait, il y a deux fichiers de propriétés : une configuration par défaut et une configuration de profil qui dépend de l'environnement (par exemple dev, test, prod client 1, prod client 2, etc.) et qui remplace certaines des valeurs par défaut.

J'ai configuré un bean placeholder de propriété dans mon contexte de printemps qui me permet d'utiliser ${} pour importer les valeurs de mes fichiers de propriétés.

Le travail des haricots ressemble à ceci :

@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {
        //Do something
            //can use DAO or other autowired beans here
    }
}

Parties pertinentes de mon contexte XML :

<!-- Enable configuration of scheduled tasks via annotations -->
    <task:annotation-driven/>

<!-- Load configuration files and allow '${}' style placeholders -->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/default-config.properties</value>
                <value>classpath:config/environment-config.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
    </bean>

J'aime vraiment ça. C'est assez simple et propre avec un minimum de XML.

J'ai toutefois une autre exigence : certains de ces emplois peuvent être totalement handicapés dans certains cas.

Donc, avant d'utiliser Spring pour les gérer, je les créais manuellement et il y a un paramètre booléen avec le paramètre cron dans les fichiers de configuration, pour spécifier si le travail doit être activé ou non :

jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?

Comment puis-je utiliser ce paramètre dans Spring pour créer conditionnellement ou tout simplement ignorer le bean, en fonction de ce paramètre de configuration ?

Une solution de contournement évidente serait de définir un modèle cron qui ne serait jamais évalué, de sorte que le travail ne soit jamais exécuté. Mais le bean serait quand même créé et la configuration serait un peu obscure, donc je pense qu'il doit y avoir une meilleure solution.

77voto

Vpn_talent Points 222

Le moyen le plus efficace de désactiver @Scheduled dans Spring est de définir l'expression cron à -

@Scheduled(cron = "-")
public void autoEvictAllCache() {
    LOGGER.info("Refresing the Cache Start :: " + new Date());
    activeMQUtility.sendToTopicCacheEviction("ALL");
    LOGGER.info("Refresing the Cache Complete :: " + new Date());
}

Desde el docs :

CRON_DISABLED

Chaîne statique publique finale CRON_DISABLED
Un cron spécial qui indique un déclencheur désactivé : "-". Cette valeur est principalement destinée à être utilisée avec les caractères de remplacement ${...}, permettant de la désactivation externe des méthodes planifiées correspondantes.

Depuis : 5.1 Voir aussi : ScheduledTaskRegistrar.CRON_DISABLED

49voto

Prabhakaran Points 10003
@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Value("${jobs.mediafiles.imagesPurgeJob.enable}")
    private boolean imagesPurgeJobEnable;

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {

         //Do something
        //can use DAO or other autowired beans here
        if(imagesPurgeJobEnable){

            Do your conditional job here...

        }
    }
}

40voto

Oleg Points 325

Vous pouvez regrouper les méthodes d'ordonnancement par conditions en un certain nombre de services et les organiser de la manière suivante :

@Service
@ConditionalOnProperty("yourConditionPropery")
public class SchedulingService {

@Scheduled
public void task1() {...}

@Scheduled
public void task2() {...}

}

35voto

tmullin Points 413

Spring Boot fournit @ConditionalOnProperty ce qui serait parfait si vous utilisiez Spring Boot. Cette annotation est une spécialisation de @Conditional introduit avec Spring 4.0.0.

En supposant que vous utilisez simplement Spring "normal" et non Spring Boot, vous pouvez créer votre propre implémentation de Condition à utiliser avec @Conditional qui imiterait @ConditionalOnProperty de Spring Boot.

27voto

user3474985 Points 771

Si vous cherchez à activer @EnableScheduling à partir d'une propriété, vous pouvez le faire dans Spring Boot en déplaçant l'annotation @EnableScheduling vers une classe de configuration et en utilisant @ConditionalOnProperty comme suit :

@Configuration
@EnableScheduling
@ConditionalOnProperty(prefix = "com.example.scheduling", name="enabled", havingValue="true", matchIfMissing = true)
public class SchedulingConfiguration {

}

Cela désactivera la programmation de l'application. Cela peut être utile dans une situation où vous souhaitez pouvoir exécuter l'application une seule fois ou de manière planifiée en fonction de la manière dont elle est lancée.

D'après le commentaire de wilkinsona ici : https://github.com/spring-projects/spring-boot/issues/12682

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X