背景
たとえば、Spring BatchをCommandLineJobRunnerを使用するjavaコマンドで起動し、そのjavaプロセスの終了ステータスをシェルスクリプトで取得して何らかの条件分岐を行いたい、とする。基本的には、Spring Batchはその終了状態に応じて0,1,2を返すのでこれで十分なのだが、それ以外の任意の値を返したい場合がある。
ソースコードなど
環境
- spring-batch 3.0.7.RELEASE
JVM終了時に呼ばれるSystemExiter
CommandLineJobRunnerはJVM呼び出し時の拡張ポイントとしてpresetSystemExiterを用意しているので、ここで自前のSystemExiterを設定できる。
import org.springframework.batch.core.launch.support.CommandLineJobRunner; import org.springframework.batch.core.launch.support.SystemExiter; ... public static void main(String[] args) throws Exception { CommandLineJobRunner.presetSystemExiter(new SystemExiter() { public void exit(int status) { System.exit(status); } }); CommandLineJobRunner.main(args); }
ちなみにEclipseで終了ステータスを確認するにはdebugビューで見れる。
afterJobでExitStausのexitCodeを指定してExitCodeMapperで変換
上のコードは固定値だが、exitメソッドのstatusは基本的にはExitStatusの値が入ってくる。ただし、CommandLineJobRunnerデフォルト動作のSimpleJvmExitCodeMapperが0,1,2のいずれかにExitStatusの値を変換する。そのため、それ以外の値にしたければ自前のExitCodeMapperを設定してやる必要がある。
まず、適当な終了ステータスのExitStatusを返すJobExecutionListenerを作る。リスナ設定のXMLなどについては省略。
import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionListener; public class JobListener implements JobExecutionListener { @Override public void beforeJob(JobExecution jobExecution) { } @Override public void afterJob(JobExecution jobExecution) { jobExecution.setExitStatus(new ExitStatus("114")); } }
自前のExitCodeMapperを作る。ここでは、単にExitStatusのexitCode文字列をintに変換するだけ。上記のJobListener#afterJobでexitCodeに114の文字列を指定しているので、以下のメソッドはintの114を返す。
import org.springframework.batch.core.launch.support.SimpleJvmExitCodeMapper; public class CustomExitCodeMapper extends SimpleJvmExitCodeMapper { @Override public int intValue(String exitCode) { return Integer.parseInt(exitCode); } }
次に、CommandLineJobRunnerにsetExitCodeMapperがあるので、これを使用してセッターインジェクションで、上で作成した自前のCustomExitCodeMapperを設定する。方法は色々あるが、たとえばXMLなら以下のようにする。
<bean id="exitCodeMapper" class="kagamihoge.springbatchexitcode.CustomExitCodeMapper" />
ここの仕組みについては、CommandLineJobRunnerは起動時に引数に与えられたxmlをスキャンし、それを自身にも適用している。なので、たとえばsetExitCodeMapper
に対応するexitCodeMapper
というidのbeanがあればそれをインジェクションする。
最後に、最初に作成したSystemExiterのところを引数の値をそのままSystem.exitの引数に渡すように変更する。
CommandLineJobRunner.presetSystemExiter(new SystemExiter() { public void exit(int status) { System.exit(status); } });
これで、afterJobで何らかの条件分岐を行い、それを基に任意の終了ステータスを返すことが出来る。