Spring cron vs cron normal?

10 minutos de lectura

avatar de usuario
Pablo

Estoy tratando de hacer que un trabajo cron funcione dentro de un proyecto heredado de Java/Spring/Hibernate, así que decidí usar el programador de primavera.

Quiero que myTask.doStuff se ejecute a las 12:00 el primer domingo de cada mes.

En mi application-context.xml he configurado mi programador de tareas como:

<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"/>

siendo la propia expresión cron del problema: 0 0 12 ? 1/1 DOM#1 *

y myTask es un bean, que tiene un método llamado doStuff que funciona perfectamente cuando se ejecuta desde pruebas unitarias.

Cuando construyo e implemento, obtengo una excepción de tiempo de arranque de Spring:

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)

Dado que estoy usando expresiones cron por primera vez, mi primera suposición fue que estaba haciendo algo mal, pero verifiqué dos veces usando fabricante de cron y me dio el mismo resultado.

Toda la documentación dice: una expresión cron es una cadena que consta de seis o siete subexpresiones (campos).1

a pesar de esto, intenté eliminar el séptimo elemento (año) ya que no está en ninguno de los ejemplos y recibí un mensaje de error diferente:

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 admite un tipo diferente de cron de todo lo demás? la documentación específica de primavera solo dice ‘expresiones cron’.

¿Cómo puedo hacer que esta expresión cron funcione como se esperaba en este contexto? Cualquier ayuda en absoluto sería apreciada.

Por el momento, mi solución sería simplificar esta expresión para que solo se ejecute todos los domingos, y anteponga algo de lógica Java para calcular qué domingo del mes es, y ver si eso funciona, pero eso anula el propósito del enfoque de configuración y parece un antipatrón.

  • Has probado 0 0 12 ? * SUN#1? (sin el último *)

    – Tomás

    17 de junio de 2015 a las 9:53

  • Sí, recibí un mensaje de error diferente: lo menciono donde digo “a pesar de esto, intenté eliminar el séptimo elemento” y enumero el mensaje de error. 🙂

    – Pablo

    17 de junio de 2015 a las 11:41

  • Spring Scheduler no admite expresiones cron demasiado ricas (no estoy seguro de que sea el caso aquí), como lo hace Quartz Scheduler. Pruébalo con cuarzo

    –Evgeni Dimitrov

    17 de junio de 2015 a las 12:05


  • @Evgeni Entonces, ¿hay diferentes ‘sabores’ de CRON? ¿Cron de SpringScheduler no es lo suficientemente expresivo para hacer este trabajo? (No quiero cambiar las dependencias si puedo evitarlo)

    – Pablo

    18 de junio de 2015 a las 9:44

avatar de usuario
Dezso Gabos

Las tareas programadas de primavera son no en el mismo formato que las expresiones cron.

No siguen el mismo formato que las expresiones cron de UNIX.

Solo hay 6 campos:

  • segundo,
  • minuto,
  • hora,
  • dia del mes,
  • mes,
  • días de la semana.

Asterisco

significa coincidir con cualquiera. */X significa “cada X” (ver ejemplos).

"0 0 18 * * MON-FRI" means every weekday at 6:00 PM. 

"0 0 */1 * * *" means every hour on the hour.

"0 0 */8 * * *" means every 8 hours on the hour.

"0 0 12 1 * *" means 12:00 PM on the first day of every month. 

Los días numéricos de la semana no me funcionan. Además, “MON-FRI” es mucho más fácil de leer. Aquí hay algunos ejemplos de expresiones: Aquí puedes encontrar algunosinformación adicional

. También puede encontrar ladocumentación de primavera útil

  • . Creo que esta es la segunda URL actualizada:

    docs.spring.io/spring-framework/docs/current/…

    – Entusiasta de Scala


  • 30 de abril de 2018 a las 14:12

    Hay una discrepancia más: en primavera, los campos ‘día’ y ‘día de la semana’ se combinan mediante la lógica AND, pero en cron es OR

    – Eugenio

  • 28 de mayo de 2018 a las 13:12

    ¿Saben si es posible convertir una expresión cron en un formato Spring?

    – Viny Machado

  • 18 abr 2019 a las 21:52

    También puede agregar una expresión de zona horaria a Spring Cron

    – anataliocs

  • 26 de febrero de 2021 a las 19:25

    respuesta impecable!

    – Gaurav

21 de mayo de 2021 a las 16:18
avatar de usuario

Ng Sek largo Tomando nota de:

https://www.baeldung.com/cron-expresiones

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)

Una tarea programada de primavera es así: Desde:

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

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)

Un trabajo de Linux Cron es así:

  • Nota al margen: Un artículo decía que es posible tener un parámetro opcional 7 que es año
  • He intentado usar la última primavera y muestra un error, así que no creo que esté funcionando. Si tu Expresión de trabajo cron de Linux es bastante simple, parece que es posible solo pon un 0 delante y se convertirá en el
    • expresión de tareas programadas de primavera
      • */5 * * * * Por ejemplo, cada 5 minutos
      • 0 */5 * * * * Trabajo cron de Linux

Tareas del horario de primavera

  1. Bonificación: Generador Cron de horario de primavera Show code snippet
  2. Haga clic en Run Code snippet
  3. Haga clic en
$('.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">SAT</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>

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad