レガシーJava/Spring/Hibernateプロジェクト内でcronジョブを動作させようとしているので、スプリングスケジューラを使用することにしました。
MyTask.doStuffを毎月第1日曜日の12:00に実行するようにします。
Application-context.xmlで、タスクスケジューラを次のように構成しました。
<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"/>
問題のcron表現自体は次のとおりです:0 0 12? 1/1 Sun#1 *
myTask
はBeanです。これには、単体テストから実行したときに完全に機能するdoStuff
というメソッドがあります。
ビルドしてデプロイすると、春からbootime例外が発生します。
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)
私が初めてcron式を使用していることを考えると、私の最初の仮定は何か間違ったことをしているということでしたが、 cronmaker を使用して二重にチェックすると、同じ結果が得られました。
すべてのドキュメントには次のように書かれています:cron式は、6つまたは7つの部分式(フィールド)で構成される文字列です。 1
それにもかかわらず、私は7番目の要素(年)をノックオフしようとしましたが、それはどの例にも含まれていないため、別のエラーメッセージが表示されました:
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は、他のすべてとは異なるフレーバーのcronをサポートしていますか? 春固有のドキュメント は単に「cron式」と言います。
このcron式をこのコンテキストで期待どおりに機能させるにはどうすればよいですか?すべての助けをいただければ幸いです。
現時点で私のソリューションは、この式を単純化して毎週日曜日に実行し、いくつかのJavaロジックを追加して月の日曜日を計算し、それが機能するかどうかを確認することですが、その種類は設定アプローチの目的を無効にし、アンチパターンのように見えます。
Springのスケジュールされたタスクは、cron式と同じ形式ではありません。
UNIX cron式と同じ形式には従いません。
6つのフィールドのみがあります:秒、分、時間、月の日、月、曜日。アスタリスク(*)は、すべてに一致することを意味します。 */Xは「すべてのX」を意味します(例を参照)。数値の曜日は機能しません。また、「MON-FRI」は読みやすくなっています。式の例を次に示します。
「0 0 18 * * MON-FRI」は、平日の午後6時を意味します。
「0 0 */1 * * *」は、毎時を意味します。
「0 0 */8 * * *」は、1時間の8時間ごとを意味します。
「0 0 12 1 * *」は、毎月1日の12:00 PMを意味します。
ここにいくつかの追加情報があります: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html
また、春のドキュメントが役立つかもしれません: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/integration.html#scheduling
以下からメモを取ります: https://www.baeldung.com/cron-expressions
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)
From: 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)
サイドノート:
*/5 * * * *
Linux cronジョブ0 */5 * * * *
春のスケジュールタスクShow code snippet
Run Code snippet
$('.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">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>