高度なメタデータの使用

JobRegistry

JobRegistry は、コンテキスト内で利用可能なジョブを追跡し、JobOperator で操作できるようにするために使用されます。また、他の場所(たとえば子コンテキスト)で作成されたジョブをアプリケーションコンテキストに一元的に収集するのにも役立ちます。カスタム JobRegistry 実装を使用して、登録されたジョブの名前やその他のプロパティを操作することもできます。フレームワークによって提供される実装は 1 つだけで、これはジョブ名からジョブインスタンスへの単純なマップ(MapJobregistry)に基づいています。

  • Java

  • XML

@EnableBatchProcessing を使用すると、MapJobregistry が提供されます。次の例は、独自の JobRegistry を構成する方法を示しています。

...
@Bean
public JobRegistry jobRegistry() throws Exception {
	return new MyCustomJobRegistry();
}
...

次の例は、XML で定義されたジョブに JobRegistry を含める方法を示しています。

<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />

Spring Batch が提供する MapJobRegistry は、アプリケーションコンテキスト内のすべてのジョブを自動で取得できるほどスマートです。ただし、JobRegistry のカスタム実装を使用している場合は、ジョブオペレータで操作するジョブを手動で取得する必要があります。

JobParametersIncrementer

JobOperator のほとんどのメソッドは自明であり、インターフェースの Javadoc でより詳細な説明を見つけることができます。ただし、startNextInstance メソッドは注目に値します。このメソッドは、常に Job の新しいインスタンスを開始します。これは、JobExecution に深刻な課題があり、Job を最初からやり直す必要がある場合に非常に役立ちます。JobLauncher (新しい JobInstance をトリガーする新しい JobParameters オブジェクトが必要) とは異なり、パラメーターが以前のパラメーターのセットと異なる場合、startNextInstance メソッドは Job に関連付けられた JobParametersIncrementer を使用して、Job を新しいインスタンスに強制します。

public interface JobParametersIncrementer {

    JobParameters getNext(JobParameters parameters);

}

JobParametersIncrementer の契約は、JobParameters オブジェクトが与えられると、それに含まれる必要な値をインクリメントして「次の」 JobParameters オブジェクトを返すことです。フレームワークは JobParameters へのどの変更が「次の」インスタンスになるかを知る方法がないため、この戦略は役に立ちます。例: JobParameters の唯一の値が日付であり、次のインスタンスを作成する必要がある場合、その値を 1 日または 1 週間ずつ増やす必要がありますか (たとえば、ジョブが毎週の場合)? 次の例に示すように、Job の識別に役立つ数値についても同じことが言えます。

public class SampleIncrementer implements JobParametersIncrementer {

    public JobParameters getNext(JobParameters parameters) {
        if (parameters==null || parameters.isEmpty()) {
            return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
        }
        long id = parameters.getLong("run.id",1L) + 1;
        return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
    }
}

この例では、run.id のキーを持つ値を使用して、JobInstances を区別しています。渡された JobParameters が null の場合、Job は以前に実行されたことがないため、初期状態を返すことができると見なすことができます。ただし、そうでない場合は、古い値が取得され、1 つインクリメントされて返されます。

  • Java

  • XML

Java で定義されたジョブの場合、次のように、ビルダーで提供される incrementer メソッドを介してインクリメンタを Job に関連付けることができます。

@Bean
public Job footballJob(JobRepository jobRepository) {
    return new JobBuilder("footballJob", jobRepository)
    				 .incrementer(sampleIncrementer())
    				 ...
                     .build();
}

XML で定義されたジョブの場合、次のように、名前空間の incrementer 属性を通じてインクリメンタを Job に関連付けることができます。

<job id="footballJob" incrementer="sampleIncrementer">
    ...
</job>

ジョブの停止

JobOperator の最も一般的な使用例の 1 つは、ジョブを正常に停止することです。

Set<Long> executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next());

特にビジネスサービスなど、フレームワークが制御できない開発者コードで現在実行が行われている場合は、即時シャットダウンを強制する方法がないため、シャットダウンは即時ではありません。ただし、制御がフレームワークに戻されるとすぐに、現在の StepExecution のステータスを BatchStatus.STOPPED に設定して保存し、終了する前に JobExecution に対して同じことを行います。

外部割り込みシグナルの処理

v6.0+ 以降、Spring Batch は、外部の中断シグナルをインターセプトしてジョブの実行を正常に停止するために JVM ランタイムに接続できる JobExecutionShutdownHook を提供します。

Thread springBatchHook = new JobExecutionShutdownHook(jobExecution, jobOperator);
Runtime.getRuntime().addShutdownHook(springBatchHook);

JobExecutionShutdownHook では、追跡するジョブ実行と、実行を停止するために使用されるジョブオペレータへの参照が必要です。

ジョブの回復

正常なシャットダウンが適切に行われなかった場合(つまり、JVM が突然シャットダウンされた場合)、Spring Batch は実行状態を正しく更新できず、失敗したジョブ実行を再開できません。この場合、ジョブ実行は再開できない STARTED 状態のままになります。このような場合、JobOperator API を使用してジョブ実行を回復することが可能です。

JobExecution jobExecution = ...; // get the job execution to recover
jobOperator.recover(jobExecution);
jobOperator.restart(jobExecution);

ジョブの中止

FAILED であるジョブ実行は再開できます (Job が再開可能な場合)。ステータスが ABANDONED のジョブ実行は、フレームワークによって再開できません。ABANDONED ステータスは、ステップ実行でも使用され、再起動されたジョブ実行でスキップ可能としてマークされます。ジョブの実行中に、前回の失敗したジョブ実行で ABANDONED とマークされたステップが検出された場合、ジョブは次のステップに進みます (ジョブフロー定義とステップ実行の終了ステータスによって決定されます)。

プロセスが停止した場合(kill -9 またはサーバー障害)、ジョブはもちろん実行されていませんが、プロセスが停止する前に誰も通知しなかったため、JobRepository は知る方法がありません。実行が失敗したか、中止されたと見なされる必要があることを手動で通知する必要があります(ステータスを FAILED または ABANDONED に変更します)。これはビジネス上の決定であり、自動化する方法はありません。再起動可能であり、再起動データが有効であることがわかっている場合にのみ、状況を FAILED に変更してください。