web-dev-qa-db-fra.com

Cron de printemps vs cron normal?

J'essaie d'obtenir un travail cron dans un projet Java/Spring/Hibernate hérité, j'ai donc décidé d'utiliser le planificateur de printemps.

Je veux que myTask.doStuff s'exécute à 12h00 le premier dimanche de chaque mois.

Dans mon application-context.xml, j'ai configuré mon planificateur de tâches comme:

<task:scheduled-tasks scheduler="MyTaskScheduler">
    <task:scheduled ref="myTask" method="doStuff" cron="0 0 12 ? 1/1 Sun#1 *"/> <!-- Every first Sundy of the month -->
</task:scheduled-tasks>

<task:scheduler id="MyTaskScheduler" pool-size="10"/>

avec l'expression cron du problème elle-même étant: 0 0 12? 1/1 Soleil # 1 *

et myTask est un bean, qui a une méthode appelée doStuff qui fonctionne parfaitement lorsqu'il est exécuté à partir de tests unitaires.

Lorsque je crée et déploie, je reçois une exception de démarrage à partir du printemps:

Caused by: Java.lang.IllegalArgumentException: cron expression must consist of 6 fields (found 7 in 0 0 12 ? 1/1 Sun#1 *)
at org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.Java:233)
at org.springframework.scheduling.support.CronSequenceGenerator.<init>(CronSequenceGenerator.Java:81)
at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.Java:54)
at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.Java:44)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.Java:129)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1417)

Étant donné que j'utilise des expressions cron pour la première fois, ma première hypothèse était que je faisais quelque chose de mal, mais j'ai vérifié deux fois en utilisant cronmaker et cela m'a donné le même résultat.

Toutes les documentations disent: Une expression cron est une chaîne composée de six ou sept sous-expressions (champs) . 1

malgré cela, j'ai essayé de supprimer le 7ème élément (année) car il ne figure dans aucun des exemples et j'ai reçu un message d'erreur différent:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.config.ScheduledTaskRegistrar#0': Invocation of init method failed; nested exception is Java.lang.NumberFormatException: For input string: "0#1"

... org.springframework.scheduling prend-il en charge une version différente de cron de tout le reste? la documentation spécifique au printemps dit juste 'expressions cron'.

Comment puis-je faire fonctionner cette expression cron comme prévu dans ce contexte? Toute aide serait appréciée.

Pour le moment, ma solution serait de simplifier cette expression pour qu'elle s'exécute tous les dimanches et d'ajouter quelques-uns Java logique pour calculer de quel dimanche du mois il s'agit, et voir si cela fonctionne - mais ce genre de défait le but de l'approche de configuration et semble comme un contre-modèle.

27
Paul

Les tâches planifiées de Spring ne sont pas au même format que les expressions cron.

Ils ne suivent pas le même format que les expressions cron UNIX.

Il n'y a que 6 champs: seconde, minute, heure, jour du mois, mois, jour (s) de la semaine. Un astérisque (*) signifie correspondre à tout. */X signifie "chaque X" (voir exemples). Les jours numériques de la semaine ne fonctionnent pas pour moi. En outre, "MON-FRI" est beaucoup plus facile à lire. Voici quelques exemples d'expressions:

"0 0 18 * * LUN-VEN" signifie tous les jours de la semaine à 18h00.

"0 0 */1 * * *" signifie toutes les heures de l'heure.

"0 0 */8 * * *" signifie toutes les 8 heures de l'heure.

"0 0 12 1 * *" signifie 12:00 PM le premier jour de chaque mois.

Ici vous pouvez trouver des informations supplémentaires: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

Vous pouvez également trouver la documentation Spring utile: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#scheduling

55
Dezso Gabos

En prenant note de: https://www.baeldung.com/cron-expressions

Une tâche planifiée Spring est comme ceci:

1 2 3 4 5 6 Index
- - - - - -
* * * * * * command to be executed
- - - - - -
| | | | | | 
| | | | | ------- Day of week (MON - Sun)
| | | | --------- Month (1 - 12)
| | | ----------- Day of month (1 - 31)
| |-------------- Hour (0 - 23)
| --------------- Minute (0 - 59)
----------------- Seconds (0 - 59)

De: https://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/

Un travail Linux Cron est comme ceci:

1 2 3 4 5 Index
- - - - -
* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Note latérale:

  • Un article a dit qu'il était possible d'avoir un paramètre 7 optionnel qui est année, j'ai essayé d'utiliser le dernier printemps et cela montre une erreur, donc je ne pense pas que cela fonctionne.
  • Si votre expression de tâche cron Linux est suffisamment simple, il semble possible de mettre simplement un 0 devant et il se convertira en expression de tâches planifiées au printemps
    • Par exemple. Toutes les 5 minutes
      • */5 * * * * Travail cron Linux
      • 0 */5 * * * * Tâches de planification du printemps

Bonus: Cron Generator de Spring Schedule

  1. Cliquer sur Show code snippet
  2. Cliquer sur Run Code snippet
  3. S'amuser!
$('.select2').select2({
  width: '100%'
});

//// Init ////////////
$dropdown = $("#secondsSelect");
for (let i = 1; i < 60; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#minSelect");
for (let i = 1; i < 60; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#hoursSelect");
for (let i = 1; i < 24; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
$dropdown = $("#dayOfMonthSelect");
for (let i = 1; i < 32; i++) {
  $dropdown.append($("<option />").val(i).text(i));
}
//// Init End ////////////


$('.select2').on('select2:select', function(e) {
  let value = e.params.data.id;
  let prevValue = $(this).val().length > 0 ? $(this).val()[0] : null;

  if (value != parseInt(value)) {
    $(this).val(value).change();
  } else if (prevValue != parseInt(prevValue)) {
    $(this).val(value).change();
  }
  calculateSpringCron();
});

let r = function(dropdown) {
  return dropdown.val().join(",");

}

let calculateSpringCron = function() {

  let result = [
    r($("#secondsSelect")),
    r($("#minSelect")),
    r($("#hoursSelect")),
    r($("#dayOfMonthSelect")),
    r($("#monthsSelect")),
    r($("#weekdaySelect")),
  ];

  $("#result").val(result.join(" "));

  $("#result-expand").html(result.join(" &nbsp; &nbsp;"))

}

calculateSpringCron();
.ms-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding-left: 3em;
  padding-right: 3em;
  background: none !important;
  padding-bottom: 5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/css/multi-select.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/js/jquery.multi-select.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>

<div class="row">
  <div class="col-12">
    <h1>Spring Schedule Cron Generator</h1>
  </div>
</div>
<div class="row">
  <div class="col-4">
    Seconds:
    <select id="secondsSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every seconds</option>
      <option value="*/2">Every even seconds</option>
      <option value="1-59/2">Every odd seconds</option>
      <option value="*/5">Every 5 seconds</option>
      <option value="*/10">Every 10 seconds</option>
      <option value="*/15">Every 15 seconds</option>
      <option value="*/30">Every 30 seconds</option>
    </select>
  </div>
  <div class="col-4">
    Minutes:
    <select id="minSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every minutes</option>
      <option value="*/2">Every even minutes</option>
      <option value="1-59/2">Every odd minutes</option>
      <option value="*/5">Every 5 minutes</option>
      <option value="*/10">Every 10 minutes</option>
      <option value="*/15">Every 15 minutes</option>
      <option value="*/30">Every 30 minutes</option>
    </select>
  </div>
  <div class="col-4">
    Hours:
    <select id="hoursSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every hour</option>
      <option value="*/2">Every even hour</option>
      <option value="1-11/2">Every odd hour</option>
      <option value="*/3">Every 3 hour</option>
      <option value="*/4">Every 4 hour</option>
      <option value="*/6">Every 6 hour</option>
    </select>
  </div>
</div>

<div class="row">
</div>

<div class="row">
  <div class="col-4">
    Days of month:
    <select id="dayOfMonthSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every day of month</option>
      <option value="*/2">Even day of month</option>
      <option value="1-31/2">Odd day of month</option>
      <option value="*/5">Every 5 days of month (5,10,15...)</option>
      <option value="*/10">Every 10 days of month (10,20,30...)</option>
    </select>
  </div>
  <div class="col-4">
    Months:
    <select id="monthsSelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every month</option>
      <option value="*/2">Even months</option>
      <option value="1-11/2">Odd months</option>
      <option value="*/4">Every 4 months</option>
      <option value="*/6">Every 6 months(half year)</option>
      <option value="1">Jan</option>
      <option value="2">Feb</option>
      <option value="3">Mar</option>
      <option value="4">Apr</option>
      <option value="5">May</option>
      <option value="6">Jun</option>
      <option value="7">Jul</option>
      <option value="8">Aug</option>
      <option value="9">Sep</option>
      <option value="10">Oct</option>
      <option value="11">Nov</option>
      <option value="12">Dec</option>
    </select>
  </div>
  <div class="col-4">
    Weekday:
    <select id="weekdaySelect" class="select2" name="states[]" multiple="multiple">
      <option value="*" selected="selected">Every weekday</option>
      <option value="MON-FRI">Weekdays (MON-FRI)</option>
      <option value="SAT,Sun">Weekend</option>
      <option value="Sun">Sun</option>
      <option value="MON">MON</option>
      <option value="TUE">TUE</option>
      <option value="WED">WED</option>
      <option value="THU">THU</option>
      <option value="FRI">FRI</option>
      <option value="SAT">MON</option>
    </select>
  </div>
</div>
<div class="row">
  <div class="col-12">
    Result:
    <input id="result" class="form-control" /> With a bit of seperation for better viewing:<br/>
    <h1 id="result-expand"></h1>
  </div>
</div>
1
Ng Sek Long