ジョブの構成

Job インターフェースには複数の実装があります。ただし、これらの実装は、提供されたビルダー (Java 構成の場合) または XML 名前空間 (XML ベースの構成の場合) の背後で抽象化されます。次の例は、Java と XML の両方の構成を示しています。

  • Java

  • XML

@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .start(playerLoad())
                     .next(gameLoad())
                     .next(playerSummarization())
                     .build();
}

Job (および通常はその中の Step)には JobRepository が必要です。JobRepository の構成は、Java Configuration を介して処理されます。

前の例は、3 つの Step インスタンスで構成される Job を示しています。ジョブ関連ビルダーには、並列化 (Split)、宣言型フロー制御 (Decision)、およびフロー定義の外部化 (Flow) に役立つ他の要素を含めることもできます。

Job インターフェースには複数の実装があります。ただし、名前空間は構成の違いを抽象化します。必要な依存関係は、名前、JobRepositoryStep インスタンスのリストの 3 つだけです。次の例では、footballJob を作成します。

<job id="footballJob">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s2" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
</job>

前述の例では、親 Bean 定義を使用してステップを作成します。特定のステップの詳細をインラインで宣言する場合のその他のオプションについては、ステップ構成に関するセクションを参照してください。XML 名前空間は、デフォルトで id または jobRepository でリポジトリを参照します。これは実用的なデフォルトです。ただし、このデフォルトを明示的にオーバーライドできます。

<job id="footballJob" job-repository="specialRepository">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s3" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
</job>

ジョブ構成には、ステップに加えて、並列化 (<split>)、宣言的フロー制御 (<decision>)、およびフロー定義の外部化 (<flow/>) に役立つ他の要素を含めることができます。

再起動性

バッチジョブを実行する際の重要な課題の 1 つは、再起動時の Job の動作に関するものです。特定の JobInstance に対して JobExecution がすでに存在する場合、Job の起動は「再起動」と見なされます。理想的には、すべてのジョブが中断したところから開始できる必要がありますが、これが不可能なシナリオもあります。このシナリオでは、新しい JobInstance が作成されることを確認するのは完全に開発者の責任です。ただし、Spring Batch はいくつかの助けを提供します。Job を再起動してはならず、常に新しい JobInstance の一部として実行する必要がある場合は、再起動可能プロパティを false に設定できます。

  • Java

  • XML

次の例は、Java で restartable フィールドを false に設定する方法を示しています。

Java 構成
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .preventRestart()
                     ...
                     .build();
}

次の例は、XML で restartable フィールドを false に設定する方法を示しています。

XML 構成
<job id="footballJob" restartable="false">
    ...
</job>

別の言い方をすれば、restartable を false に設定すると、「この Job は再起動をサポートしていません」という意味になります。再起動できない Job を再起動すると、JobRestartException がスローされます。次の JUnit コードにより、例外がスローされます。

Job job = new SimpleJob();
job.setRestartable(false);

JobParameters jobParameters = new JobParameters();

JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);

try {
    jobRepository.createJobExecution(job, jobParameters);
    fail();
}
catch (JobRestartException e) {
    // expected
}

再起動不可能なジョブの JobExecution を最初に作成しようとしても、課題は発生しません。ただし、2 回目の試行では JobRestartException がスローされます。

ジョブ実行のインターセプト

Job の実行中に、カスタムコードを実行できるように、ライフサイクル内のさまざまなイベントの通知を受け取ると便利な場合があります。SimpleJob は、適切なタイミングで JobListener を呼び出すことにより、これを可能にします。

public interface JobExecutionListener {

    void beforeJob(JobExecution jobExecution);

    void afterJob(JobExecution jobExecution);
}

ジョブにリスナーを設定することにより、JobListeners を SimpleJob に追加できます。

  • Java

  • XML

次の例は、Java ジョブ定義にリスナーメソッドを追加する方法を示しています。

Java 構成
@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
                     .listener(sampleListener())
                     ...
                     .build();
}

次の例は、リスナー要素を XML ジョブ定義に追加する方法を示しています。

XML 構成
<job id="footballJob">
    <step id="playerload"          parent="s1" next="gameLoad"/>
    <step id="gameLoad"            parent="s2" next="playerSummarization"/>
    <step id="playerSummarization" parent="s3"/>
    <listeners>
        <listener ref="sampleListener"/>
    </listeners>
</job>

Job の成功または失敗に関係なく、afterJob メソッドが呼び出されることに注意してください。成功または失敗を判断する必要がある場合は、JobExecution からその情報を取得できます。

public void afterJob(JobExecution jobExecution){
    if (jobExecution.getStatus() == BatchStatus.COMPLETED ) {
        //job success
    }
    else if (jobExecution.getStatus() == BatchStatus.FAILED) {
        //job failure
    }
}

このインターフェースに対応するアノテーションは次のとおりです。

  • @BeforeJob

  • @AfterJob

親ジョブからの継承

ジョブのグループが類似しているが同一ではない構成を共有している場合、具体的な Job インスタンスがプロパティを継承できる「親」 Job を定義すると役立つ場合があります。Java のクラス継承と同様に、「子」 Job はその要素と属性を親のものと結合します。

次の例では、baseJob はリスナーのリストのみを定義する抽象 Job 定義です。Job (job1) は、baseJob からリスナーのリストを継承し、独自のリスナーリストとマージして、2 つのリスナーと 1 つの Step (step1) を持つ Job を生成する具体的な定義です。

<job id="baseJob" abstract="true">
    <listeners>
        <listener ref="listenerOne"/>
    <listeners>
</job>

<job id="job1" parent="baseJob">
    <step id="step1" parent="standaloneStep"/>

    <listeners merge="true">
        <listener ref="listenerTwo"/>
    <listeners>
</job>

詳細については、親ステップからの継承のセクションを参照してください。

JobParametersValidator

XML 名前空間で宣言されたジョブ、または AbstractJob のサブクラスを使用して宣言されたジョブは、オプションで、実行時にジョブパラメーターのバリデーターを宣言できます。これは、たとえば、ジョブがすべての必須パラメーターで開始されていることを表明する必要がある場合に役立ちます。単純な必須パラメーターとオプションパラメーターの組み合わせを制約するために使用できる DefaultJobParametersValidator があります。より複雑な制約については、インターフェースを自分で実装できます。

  • Java

  • XML

バリデーターの構成は、Java ビルダーを介してサポートされます。

@Bean
public Job job1(JobRepository jobRepository) {
    return new JobBuilder("job1", jobRepository)
                     .validator(parametersValidator())
                     ...
                     .build();
}

次の例に示すように、バリデーターの構成は、ジョブの子要素を介して XML 名前空間を介してサポートされます。

<job id="job1" parent="baseJob3">
    <step id="step1" parent="standaloneStep"/>
    <validator ref="parametersValidator"/>
</job>

バリデーターは、参照として(前に示したように)、または beans 名前空間でネストされた Bean 定義として指定できます。