再起動のための Step の構成

"ジョブの構成と実行" セクションでは、Job の再起動について説明しました。再起動はステップに多くの影響を与えるため、特定の構成が必要になる場合があります。

開始制限の設定

Step を開始できる回数を制御したいシナリオは数多くあります。例: 特定の Step を 1 回だけ実行するように構成する必要がある場合があります。これは、再実行する前に手動で修正する必要があるリソースが無効になるためです。これは、ステップごとに要件が異なる場合があるため、ステップレベルで構成できます。一度だけ実行できる Step は、無限に実行できる Step と同じ Job の一部として存在できます。

  • Java

  • XML

次のコードフラグメントは、Java での開始制限設定の例を示しています。

Java 構成
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("step1", jobRepository)
				.<String, String>chunk(10, transactionManager)
				.reader(itemReader())
				.writer(itemWriter())
				.startLimit(1)
				.build();
}

次のコードフラグメントは、XML での開始制限設定の例を示しています。

XML 構成
<step id="step1">
    <tasklet start-limit="1">
        <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
    </tasklet>
</step>

前の例で示したステップは、1 回だけ実行できます。再度実行しようとすると、StartLimitExceededException がスローされます。start-limit のデフォルト値は Integer.MAX_VALUE であることに注意してください。

完了した Step の再起動

再開可能なジョブの場合、最初に成功したかどうかに関係なく、常に実行する必要がある 1 つ以上のステップが存在する場合があります。例としては、処理前にリソースをクリーンアップする検証ステップまたは Step があります。再始動されたジョブの通常の処理中に、ステータスが COMPLETED (すでに正常に完了したことを意味する) のステップはスキップされます。allow-start-if-complete を true に設定すると、ステップが常に実行されるようにこれが上書きされます。

  • Java

  • XML

次のコードフラグメントは、Java で再起動可能なジョブを定義する方法を示しています。

Java 構成
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("step1", jobRepository)
				.<String, String>chunk(10, transactionManager)
				.reader(itemReader())
				.writer(itemWriter())
				.allowStartIfComplete(true)
				.build();
}

次のコードは、再起動可能なジョブを XML で定義する方法を示しています。

XML 構成
<step id="step1">
    <tasklet allow-start-if-complete="true">
        <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
    </tasklet>
</step>

Step 再起動の構成例

  • Java

  • XML

次の Java の例は、再起動可能なステップを持つようにジョブを構成する方法を示しています。

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

@Bean
public Step playerLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("playerLoad", jobRepository)
			.<String, String>chunk(10, transactionManager)
			.reader(playerFileItemReader())
			.writer(playerWriter())
			.build();
}

@Bean
public Step gameLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("gameLoad", jobRepository)
			.allowStartIfComplete(true)
			.<String, String>chunk(10, transactionManager)
			.reader(gameFileItemReader())
			.writer(gameWriter())
			.build();
}

@Bean
public Step playerSummarization(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("playerSummarization", jobRepository)
			.startLimit(2)
			.<String, String>chunk(10, transactionManager)
			.reader(playerSummarizationSource())
			.writer(summaryWriter())
			.build();
}

次の XML の例は、再起動可能なステップを持つようにジョブを構成する方法を示しています。

XML 構成
<job id="footballJob" restartable="true">
    <step id="playerload" next="gameLoad">
        <tasklet>
            <chunk reader="playerFileItemReader" writer="playerWriter"
                   commit-interval="10" />
        </tasklet>
    </step>
    <step id="gameLoad" next="playerSummarization">
        <tasklet allow-start-if-complete="true">
            <chunk reader="gameFileItemReader" writer="gameWriter"
                   commit-interval="10"/>
        </tasklet>
    </step>
    <step id="playerSummarization">
        <tasklet start-limit="2">
            <chunk reader="playerSummarizationSource" writer="summaryWriter"
                   commit-interval="10"/>
        </tasklet>
    </step>
</job>

前の構成例は、フットボールの試合に関する情報を読み込んで要約するジョブ用です。これには playerLoadgameLoadplayerSummarization という 3 つのステップが含まれます。playerLoad ステップはフラットファイルからプレーヤー情報をロードしますが、gameLoad ステップはゲームに対して同じことを行います。最後のステップ playerSummarization では、提供されたゲームに基づいて各プレイヤーの統計を要約します。playerLoad によってロードされたファイルは 1 回だけロードする必要があると想定されていますが、gameLoad は特定のディレクトリ内で見つかったすべてのゲームをロードし、データベースに正常にロードされた後に削除できます。その結果、playerLoad ステップには追加の構成は含まれません。完了していればスキップして何度でも開始できます。ただし、gameLoad ステップは、最後に実行してから余分なファイルが追加された場合に備えて、毎回実行する必要があります。allow-start-if-complete を true に設定して、常に起動します。(ゲームがロードされるデータベーステーブルには、要約ステップによって新しいゲームが適切に検出されるようにするためのプロセスインジケータがあると想定されています)。ジョブで最も重要な要約ステップは、開始制限が 2 になるように構成されています。これは、ステップが継続的に失敗した場合、ジョブの実行を制御するオペレーターに新しい終了コードが返されるため、便利です。手動による介入が行われるまで、再起動できません。

このジョブはこのドキュメントの例を提供するものであり、サンプルプロジェクトで見つかった footballJob とは異なります。

このセクションの残りの部分では、footballJob の例の 3 つの実行のそれぞれで何が起こるかを説明します。

実行 1:

  1. playerLoad が実行されて正常に完了し、400 人のプレーヤーが PLAYERS テーブルに追加されます。

  2. gameLoad は 11 ファイル分のゲームデータを実行および処理し、その内容を GAMES テーブルにロードします。

  3. playerSummarization は処理を開始し、5 分後に失敗します。

実行 2:

  1. playerLoad はすでに正常に完了しているため実行されず、allow-start-if-complete は false (デフォルト) です。

  2. gameLoad が再び実行され、別の 2 つのファイルが処理され、その内容が GAMES テーブルにもロードされます (まだ処理されていないことを示すプロセスインジケータが表示されます)。

  3. playerSummarization は残りのすべてのゲームデータの処理(プロセスインジケーターを使用したフィルター処理)を開始し、30 分後に再び失敗します。

実行 3:

  1. playerLoad はすでに正常に完了しているため実行されず、allow-start-if-complete は false (デフォルト) です。

  2. gameLoad が再び実行され、別の 2 つのファイルが処理され、その内容が GAMES テーブルにもロードされます (まだ処理されていないことを示すプロセスインジケータが表示されます)。

  3. これは playerSummarization の 3 回目の実行であり、その制限は 2 のみであるため、playerSummarization は開始されず、ジョブは直ちに強制終了されます。制限を上げるか、Job を新しい JobInstance として実行する必要があります。