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.
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
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
- Bonificación: Generador Cron de horario de primavera
Show code snippet
- Haga clic en
Run Code snippet
- 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(" "))
}
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>
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