118 votes

Quartz : Une expression Cron qui ne s'exécutera jamais

Je sais qu'il y a un doublon aquí Ce qui est probablement exactement mon cas, même si cela mériterait une meilleure explication, que je vais essayer de fournir ici.

Je travaille avec une application web Java utilisant un contexte d'application Spring. Dans ce contexte, j'ai défini des tâches planifiées en utilisant Quartz. Ces travaux sont déclenchés par un cron défini dans un fichier .properties.

Le contexte Spring est intégré dans le war, tandis que le fichier .properties se trouve sur le serveur d'application (Tomcat dans ce cas précis).

Ceci est très bien et permet de définir des crons différents selon l'environnement (développement, intégration, production, ...).

Maintenant, lorsque j'exécute cette application localement sur mon propre ordinateur, je ne souhaite pas que ces travaux soient exécutés. Existe-t-il un moyen d'écrire une expression cron qui ne se déclenchera jamais ?

103voto

Chop Points 1971

TL;DR

Dans Quartz 1, vous pouvez utiliser ce cron : 59 59 23 31 12 ? 2099 (dernière date valable).
Dans Quartz 2, vous pouvez utiliser ce cron : 0 0 0 1 1 ? 2200

Utiliser une expression loin dans le futur

J'ai effectué quelques tests rapides en utilisant org.quartz.CronExpression .

String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
System.out.println(valid);
if (valid) {
    CronExpression cronExpression = new CronExpression(exp);
    System.out.println(cronExpression.getNextValidTimeAfter(new Date()));
}

Quand je le fais String exp = "# 0 0 0 1 1 ?"; le isValid les résultats des tests false .

Avec l'exemple donné ci-dessus, la sortie est la suivante :

true
null

C'est-à-dire :

  • l'expression est valide ;
  • il n'y a pas de date à venir qui corresponde à cette expression.

Pour que le planificateur accepte un déclencheur cron, cependant, le dernier doit correspondre à une date dans le futur.

J'ai essayé sur plusieurs années et je me suis rendu compte qu'une fois que l'année est supérieure à 2300, Quartz semble ne plus s'en préoccuper (bien que je n'aie pas trouvé de mention d'une valeur maximale pour l'année). dans la documentation de Quartz 2 ). Il existe peut-être une façon plus propre de procéder, mais cela répond à mes besoins pour l'instant.

Donc, au final, le cron que je propose est 0 0 0 1 1 ? 2200 .

Quartz 1 variante

Notez que, dans le Quartz 1, 2099 est la dernière année valide . Vous pouvez donc adapter votre expression cron pour utiliser Suggestion de Maciej Matys : 59 59 23 31 12 ? 2099

Alternative : Utiliser une date dans le passé

Arnaud Denoyelle a proposé quelque chose de plus élégant, que mon test ci-dessus valide comme une expression correcte : au lieu de choisir une date dans un futur lointain, choisissez-la dans un passé lointain :

0 0 0 1 1 ? 1970 (la première expression valide selon la documentation de Quartz).

Cette solution ne fonctionne cependant pas.

hippofluff a mis en évidence que Quartz détectera une expression dans le passé qui ne sera plus jamais exécutée et lancera donc une exception.

org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.

Cela semble avoir été dans Quartz pendant un long moment .

Leçons apprises : le test n'est pas infaillible tel quel

Cela met en évidence une faiblesse de mon test : dans le cas où vous voulez tester un CronExpression Souvenez-vous. il doit avoir un nextValidTime 1 . Sinon, le planificateur auquel vous le transmettrez le rejettera simplement avec l'exception mentionnée ci-dessus.

Je conseillerais d'adapter le code de test comme suit :

String exp = "0 0 0 1 1 ? 3000";
boolean valid = CronExpression.isValidExpression(exp);
if (valid) {
    CronExpression cronExpression = new CronExpression(exp);
    valid = cronExpression.getNextValidTimeAfter(new Date()) != null;
}
System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail."));

Et voilà : pas besoin de réfléchir, il suffit de lire le résultat.


<sup>1 </sup>C'est la partie que j'ai oubliée lorsque j'ai testé la solution d'Arnaud en me ridiculisant et en prouvant que mon test n'était pas à ma hauteur.

53voto

Eric Tjossem Points 2006

Techniquement, les valeurs valides pour le champ facultatif Année de quartz sont 1970-2099, donc 2300 n'est pas une valeur attendue. Je suppose que vous realmente doit le faire et votre version de Quartz tente d'appliquer une syntaxe cron valide (jour 1-31, mois 1-12, etc.).

J'utilise actuellement le code suivant dans Resque-scheduler for Rails, qui accepte les informations de planification au format crontab validé, pour créer une tâche de test à exécution manuelle uniquement :

cron: "0 5 31 2 *"

Le travail attendra patiemment le début de la matinée 31 février avant de courir. Pour un équivalent en Quartz crontrigger essayez cette ligne ou une variante de celle-ci :

0 0 5 31 2 ?

25voto

metyl Points 51

Essayez-le : 59 59 23 31 12 ? 2099

19voto

icyerasor Points 1335

Si vous utilisez l'expression dans un @Scheduled(cron="") expression (qui n'utilise pas techniquement le quartz, mais qui est plutôt commune avec le printemps de cette époque) vous ne pouvez pas utiliser la solution de l'année future à 7 champs mais ces options :

  • Si vous utilisez spring 5.1+ (springBoot 2.1+), utilisez simplement "${your.cron.prop:-} et ne définissez pas la propriété pour désactiver l'exécution - voir @Scheduled . Ou définissez la propriété elle-même à "-" (veillez à utiliser des guillemets si vous utilisez un yml).
  • Désactiver le bean/service avec la commande @Scheduled en utilisant, par exemple, une méthode de type @ConditionalOnProperty("my.scheduleproperty.active") et ne pas paramétrer la propriété (ou la paramétrer en tant que false )

19voto

Pallav Chanana Points 1

Bonjour, vous pouvez essayer ceci, cela n'exécutera jamais votre programme. il suffit de le passer en tant que - dans le cron

 @Scheduled(cron = "${schedular.cron.expression}")

schedular.cron.expression=-

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