この記事では、Spring Batch を CLI で実行した際に任意の終了コードを返す方法を解説します。
CLI で実行するには CommandLineRunner を利用してますが、この基本的な実行方法については以下の記事を参照ください。
Spring Batch を利用する際は、shell 等を利用してコマンドライン経由で実行するケースは多いかと思います。そのとき、デフォルトの 0, 1, 2 ではなく、バッチアプリケーション固有の数値を返したい場合はあると思います。また、返却コードのパターンもより多く必要になることも考えられます。
CommandLineJobRunner
の場合のやり方だったり、xml ベースでのやり方は記事があったのですが、CommandLineRunner かつ java で完結する記事は少ない(というか見つけられませんでした)。
歴史が長いことは良いことですが、歴史が長いゆえに一般的な方法が探しづらいですね。
コードは前回の続きにしています。
対応方法
やることは以下です。
- 終了コードの定義
- 処理終了後に終了コードを設定
- 終了コードを返却する
終了コードの定義(SimpleJvmExitCodeMapper)
エラーコードは SimpleJvmExitCodeMapper
を継承することでカスタマイズ可能です。
SimpleJvmExitCodeMapper
クラス自体にもコンストラクタで定義はされていますが、継承した場合は終了コードの全パターンを再定義する必要があります。以下は、元々用意されている定義に対して、別の終了コードを指定しつつ、カスタムの ExitStatus を定義したものです。
@Component
public class MyBatchExitCodeMapper extends SimpleJvmExitCodeMapper {
Map<String, Integer> mapping = new HashMap<String, Integer>();
private MyBatchExitCodeMapper () {
mapping.put(ExitStatus.COMPLETED.getExitCode(), Integer.valueOf(100));
mapping.put(ExitStatus.EXECUTING.getExitCode(), Integer.valueOf(101));
mapping.put(ExitStatus.FAILED.getExitCode(), Integer.valueOf(102));
mapping.put(ExitStatus.NOOP.getExitCode(), Integer.valueOf(103));
mapping.put(ExitStatus.STOPPED.getExitCode(), Integer.valueOf(104));
mapping.put(ExitStatus.UNKNOWN.getExitCode(), Integer.valueOf(105));
mapping.put("CUSTOM_STATUS", Integer.valueOf(255));
setMapping(mapping);
}
@Override
public int intValue(String exitCode) {
return mapping.get(exitCode);
}
}
終了コードの設定(ExitCodeGenerator)
終了コードを定義しても、それをアプリケーションの戻り値として設定しないといけません。
SpringApplication
の戻り値は ExitCodeGenerator
を利用することで指定が可能です。getExitCode
を実装し、run
の中で設定します。ここではジョブ実行結果の戻り値に対応するコードを終了コードとしています。
public class MyBatchCommandLineRunner implements CommandLineRunner, ExitCodeGenerator {
...
private int exitCode;
@Override
public int getExitCode() {
return exitCode;
}
...
@Override
public void run(String... args) throws Exception {
...
// exitCodeMapper.intValue で定義した戻り値の map から対応する終了コードを取得します
int returnValue = exitCodeMapper.intValue(jobExecution.getExitStatus().getExitCode());
// 終了コードを設定
this.exitCode = returnValue;
}
}
終了コードを返却する
Java プロセスとしての終了コードは System.exit
メソッドで指定できます。
そこに、SpringApplication
の実行の戻り値(上で設定した exitCode )を指定します。
@SpringBootApplication
public class SpringBatchCliApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(SpringBatchCliApplication.class);
int exitCode = SpringApplication.exit(app.run(args));
System.out.println("exit status: " + exitCode);
System.exit(exitCode);
}
}
実行
実際に期待した結果になるかの確認です。
Tasklet でカスタムステータスを指定する
Tasklet でステップの ExitStatus
を CUSTOM_STATUS
に指定します。
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext context) {
...
contribution.setExitStatus(new ExitStatus("CUSTOM_STATUS"));
....
}
結果は以下の通り。255
になってますね。
試しに、今度は new ExitStatus("CUSTOM_STATUS")
の部分を、ExitStatus.FAILED
にすると、ちゃんと 102 になります。
ステップ の結果によって ジョブの ExitStatus を変える
今度は Tasklet でステップの ExitStatus を指定した後、その結果によってジョブの ExitStatus を変えてみます。変更は JobExecutinListenerSupport
の afterJob
で行います。
以下では、ステップの実行結果に FAILED
があると、ジョブの結果を CUSTOM_STATUS
にしています。
public class BatchJobListener extends JobExecutionListenerSupport {
....
@Override
public void afterJob(JobExecution jobExecution) {
System.out.println("aftefJob");
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
if (stepExecution.getExitStatus().getExitCode().equals("FAILED")) {
jobExecution.setExitStatus(new ExitStatus("CUSTOM_STATUS"));
return;
}
}
}
}
結果だけ見ても代わり映えしませんが、ちゃんと 255 が返ってきています。
まとめ
分かってしまえば、数行で終了コードが指定でき、カスタマイズも自由にできました。
また、ステップの実行結果によっても柔軟に終了コードが設定できそうです。
コメント