読者です 読者をやめる 読者になる 読者になる

M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

Spring Batchの用語とステレオタイプ

今度は公式リファレンスから、Spring Batchフレームワークの用語と「ステレオタイプ」について。

ここで「ステレオタイプ」とは「フレームワークを利用するにあたって必要になるオブジェクト・グラフの構成要素」とか「フレームワークの中である限定された役割を負わされたオブジェクト」とかそのような意味です。Spring Web MVCなどでは@Serviceアノテーションなどに関してこの用語が登場したような気がします。いずれにせよ社会科学あがりの人間にはちょっと戸惑いがあります。

今回はこうしたわりと概念的なことをとにかく押さえておきたいというのが目的ですので、リファレンスも斜め読み的に訳出しました。原典は"Spring Batch - Reference Documentation"(3.0.2.RELEASE。2014/12/29取得)の第3章「バッチのドメイン言語」です。原典には図表などもあります。そちらも見ておいたほうがわかりやすいかもしれません。

          * * *

3.1 ジョブ

このセクションではバッチ・ジョブの概念に関わるステレオタイプについて説明します。 Jobは独立したバッチ処理を包み込むものです。他のSpringプロジェクトのオブジェクトと同様に、JobXMLコンフィギュレーションもしくはJavaコード・ベースのコンフィギュレーションにより組み立てられることになります。この過程は「ジョブ・コンフィギュレーション」と呼ばれます。Jobは〔Spring Batchを構成する〕階層構造全体のなかの最上部に位置づけられます。

〔・・・中略・・・〕

Spring Batchでは、ジョブはステップのコンテナに外なりません。ジョブにより複数のステップが1つの流れのなかで論理的に組み合わされ、再実行できるかどうかというような、すべてのステップに共通のプロパティの設定が可能になります。ジョブ・コンフィギュレーションには次のものが含まれます:

  • ジョブの単純名
  • ステップの内容定義とその実行順序の定義
  • ジョブが再実行できるかどうかの指定

Jobインターフェースのデフォルトの簡素な実装がSpring Batchにより提供されています。SimpleJobクラスはJobインターフェースの上にいくつかの標準的な機能を盛り込んでいます。しかし〔XMLコンフィギュレーションの〕バッチ名前空間を用いることで、このクラスを直接に初期化せずに済みます〔つまりSimpleJobというクラス名は忘れてよいということです〕。<job>は次のように使うことができます:

<job id="footballJob">
    <step id="playerload" next="gameLoad"/>
    <step id="gameLoad" next="playerSummarization"/>
    <step id="playerSummarization"/>
</job>

3.1.1 ジョブ・インスタンス

JobInstanceは論理的なジョブ実行の概念を指し示すものです。先ほどの図〔訳注:こちらが原典の図です。〕の「EndOfDay」ジョブのように、一日の終りに1回だけ実行されるバッチ・ジョブについて考えてみましょう。「EndOfDay」という名前のJobが1つあります。しかしこのJobの各回の実行は、個別に記録されなくてはなりません。このジョブのケースでは、論理的な JobInstanceは1日あたり1つ存在することになります。例えば1月1日のジョブ実行に対応するジョブ・インスタンスが1つ、続いて1月2日にも1つ・・・といった具合です。もし1月1日の実行が最初失敗し次の日に再度実行したとしたら、それは依然として1月1日の実行なのです。(ふつうこの実行にはその日に処理されるデータが対応付けられます。つまり1月1日の実行は1月1日のデータに対応したものになります。)したがって、各JobInstance複数の「実行」( JobExecution についてより詳しくは後述します)を持つことができるとともに、ある一時においては単一のJobInstanceと該当のJobの対応関係と、特定のJobParameterのみが存在しうるということになります。

JobInstanceの定義はバッチ・ジョブにより読み込まれるであろうデータとはまったく何の関わりもありません。どのようなデータが読み込まれるかというのはもっぱら ItemReader の実装次第ということです。例えば、「EndOfDay」の話でいえば、「有効日付」〔effective date〕とか「予定日」〔schedule date〕のようなカラムがあってそのデータが何日に属するものなのかを示すと仮定しましょう。そうすると、1月1日の実行では1日目のデータのみが読み込まれ、1月2日の実行では2日目のデータのみが読み込まれるといった具合です。これは業務的な決めの問題でしょうから、ItemReader に一任されます。同じ JobInstance が使われるかどうかによって、前回実行時の「状態」(すなわち ExecutionContext ですが、これについては後述します)を使用するかどうかが決まります。新しいJobInstanceが使用される場合、「最初からはじめる」ことを意味になり、既存のインスタンス〔訳注:これは「等価と見なされるインスタンス」という意味であり、これこそが本節冒頭の「論理的な・・・」という形容の意味するところのようです〕を使う場合、一般的には「中断したところから始める」という意味になります。

3.1.2 ジョブ・パラメータ

JobInstanceの概念とそれがJobとどう違うかについての議論をしてきました。ここで当然の疑問は次のようなものでしょう:「ある JobInstanceは他のそれとどのように区別されるのか?」これに対する答えは次のようになります:「それは JobParameters によってである。」 JobParameters はバッチ・ジョブを起動するにあたり使用されたパラメータのセットです。その値はジョブ・インスタンスの識別に用いることができ、実行中に参照することができます。

〔・・・中略・・・〕

前述の例では、2つのジョブ・インスタンスが登場しました。1つは1月1日、そしてもう1つが1月2日です。ジョブ自体はただ1つですが、1月1日のジョブ・パラメータで起動されたインスタンスと、1月2日のジョブ・パラメータで起動されたインスタンスとがありました。ということで、要約するとこうなります:JobInstance = Job + JobParametersによる識別。この点を理解することは、ある JobInstanceがどのように定義されるかを開発者が有効に制御することを可能にします。というのもその制御とはすなわちジョブに対してどんなパラメータを渡すかということだからです。

NOTE: すべてのジョブ・パラメータが JobInstanceの識別に関わるとは限りません。デフォルトではすべてのパラメータが識別に使用されますが、Spring Batchフレームワーク JobInstanceの識別に用いられないパラメータを伴うJobを作ることを許しています。

3.1.3 ジョブ実行

1つのJobExecutionJob実行の試みの特定の1回を指す技術的な概念です。ジョブ実行は失敗に終わるかもしれませんし成功に終わるかもしれません。その実行に対応する JobInstance は実行結果について関知しません。前述のEndOfDay Jobの例を使って説明すると、1月1日分の JobInstance は最初失敗という結果となりました。ここで、最初と同じパラメータ(1月1日)を与えて同じジョブを実行すると、新しい JobExecution が生成されます。しかしJobInstanceは1つのままです。

Job はバッチ・ジョブの処理内容とそれがどのように実行されるかを定義するものです。そして JobInstance は主に意味論上等価な再実行を適切に行えるようにするため複数のジョブ実行をまとめる、純粋に構成された概念です。これに対して JobExecutionは、ジョブの実行中に起こった出来事や制御され永続化されなくてはならない各種のプロパティを記録するための機能です。

Table 3.1. ジョブ実行のプロパティ

status BatchStatus型。このオブジェクトは、当該のジョブ実行のスタータスを表します。実行中はBatchStatus.STARTED、失敗するとBatchStatus.FAILED、そして成功裡に済めばBatchStatus.COMPLETEDです。
startTime java.util.Date型。この値はジョブ実行が開始されたときの当該システム時間を表します。
endTime java.util.Date型。この値はジョブ実行が終了したときの当該システム時間を表します。実行結果については関知しません。
exitStatus ExitStatus型。実行結果を表します。これはもっとも重要な項目です。終了コードは呼び出し元に返されるためです。詳しくは第5章を参照してください。
createTime java.util.Date型。この値はジョブ実行が最初に記録されたときの当該システム時間を表します。ジョブはまだ開始されていないかもしれませんが(するとstartTimeはまだ存在しません)、createTimeは必ず存在します。この値はフレームワークがジョブ・レベルでExecutionContextを管理するのに必要とされます。
lastUpdated java.util.Date型。この値はジョブ実行が最後に記録されたときの当該システム時間を表します。
executionContext この「プロパティ袋」は実行中に保存しておく必要のあるあらゆるユーザ・データ〔フレームワークに由来しない、バッチ・ジョブ固有の情報〕を保持します。
failureExceptions ジョブ実行中に遭遇した例外のリスト。ジョブ実行の失敗に際して複数の例外が発生した場合に〔それらの情報にアクセスするのに〕便利です。

〔・・・中略・・・〕

3.2 Stepステップ

Stepはバッチ・ジョブのなかで逐次的に実行されるべき独立した処理をカプセル化するドメイン・オブジェクトです。すべてのJob は1つかもしくはそれ以上のステップから構成されます。Step は実際のバッチ処理の内容を規定しそれを制御するためのすべての情報を内包しています。これはどうしても不明瞭な説明となってしまいます。というのも、結局のところStepの内容はJobをつくる開発者の判断で決まることだからです。ステップは開発者の好み次第で、シンプルなものにすることも、反対に複雑なものにすることもできます。シンプルなStep であればファイルからデータをロードし、それをデータベースに登録するだけかもしれません。その場合コードはほんの少し、あるいはまったく書かずに済むかもしれません。(使用する実装次第です。)複雑なStep であれば難しい業務ルールを持っており、それが処理の一部に適用されるかもしれません。Jobの場合と同じく、Stepもまた独自の StepExecution を持ちます。このオブジェクトは一意の JobExecutionに対応します。

3.2.1 StepExecutionステップ実行

StepExecutionStep実行の試みの特定の1回を表します。 StepExecution JobExecution と同様にしてStep が実行されるたびに生成されます。ただし先行するステップが失敗したことにより当該ステップの実行が失敗した場合には StepExecution は記録されません。StepExecution はそのStepが実際に起動した時にだけ生成されるのです。

ステップ実行はStepExecution クラスのインスタンスにより表されます。それぞれのインスタンスは対応するステップとJobExecutionへの参照やコミットとロールバックの回数のようなトランザクション関連データ、開始と終了の時間を保持しています。これに加えて、各ステップ実行はExecutionContextへの参照も保持します。このオブジェクトはバッチ実行のあいだ保持されている必要のある、バッチ・ジョブに固有のあらゆるデータ──例えば、各種統計情報や再実行に必要となる状態情報など──を内包しています。次に示すのはStepExecutionのプロパティの一覧です。

Table 3.8. ステップ実行のプロパティ

status BatchStatus型。このオブジェクトは、当該のジョブ実行のスタータスを表します。実行中はBatchStatus.STARTED、失敗するとBatchStatus.FAILED、そして成功裡に済めばBatchStatus.COMPLETEDです。
startTime java.util.Date型。この値はジョブ実行が開始されたときの当該システム時間を表します。
endTime java.util.Date型。この値はジョブ実行が終了したときの当該システム時間を表します。実行結果については関知しません。
exitStatus ExitStatus型。実行結果を表します。これはもっとも重要な項目です。終了コードは呼び出し元に返されるためです。詳しくは第5章を参照してください。
createTime java.util.Date型。この値はジョブ実行が最初に記録されたときの当該システム時間を表します。ジョブはまだ開始されていないかもしれませんが(するとstartTimeはまだ存在しません)、createTimeは必ず存在します。この値はフレームワークがジョブ・レベルでExecutionContextを管理するのに必要とされます。
lastUpdated java.util.Date型。この値はジョブ実行が最後に記録されたときの当該システム時間を表します。
executionContext この「プロパティ袋」は実行中に保存しておく必要のあるあらゆるユーザ・データ〔フレームワークに由来しない、バッチ・ジョブ固有の情報〕を保持します。
readCount 成功裡に読み込むことのできた入力アイテムの数。
writeCount 成功裡に書き込むことのできた出力アイテムの数。
commitCount 当該の実行によりコミットされたトランザクションの数。
rollbackCount 当該ステップがロールバックされたことにより影響を被った業務トランザクションの回数。
readSkipCount 読み込みに失敗し、入力アイテムのスキップが発生した回数。
processSkipCount 中間処理に失敗し、処理アイテムのスキップが発生した回数。
filterCount ItemProcessorによりフィルターされたアイテムの数。
writeSkipCount 書き込みに失敗し、出力アイテムのスキップが発生した回数。

3.3 実行コンテキスト

ExecutionContextは、フレームワークにより永続化され制御されるキーと値のペアのコレクションであり、開発者に対してStepExecutionもしくはJobExecutionのスコープで状態を保存する場所を提供するものです。Quartzに親しんでいる方であれば、JobDataMapに非常に近しいものと感じられるでしょう。もっともよく利用される例としては再実行の際の手助けです。 フラット・ファイルを入力とする例を考えてみましょう。個別の行を処理中、フレームワークはコミット・ポイントのたびに ExecutionContextを永続化します。これによりItemReader は実行中に致命的なエラーが発生したり、電源喪失したりしたときの状態を保存しておくことが可能になります。このために必要なことは各時点における読み込んだ行数を実行コンテキストに追加するだけです。残りの仕事〔定期的な永続化とその復元〕はフレームワークがやってくれます:

executionContext.putLong(getKey(LINES_READ_COUNT), reader.getPosition());

〔・・・中略・・・〕

3.4 JobRepository

JobRepositoryはこれまで説明してきたすべてのステレオタイプの情報を永続化するメカニズムです。リポジトリJobLauncherJob、そしてStep実装のためにCRUD操作APIを提供します。Jobが最初に起動したとき、JobExecutionリポジトリから取得され、ジョブの実行中、一連のStepExecutionJobExecutionリポジトリに渡されて永続化されます:

<job-repository id="jobRepository"/>

3.5 ジョブ・ランチャー

JobLauncher JobParameters のセットともにJobを起動するためのシンプルなインターフェースです:

public interface JobLauncher {

    public JobExecution run(Job job, JobParameters jobParameters)
                throws JobExecutionAlreadyRunningException, JobRestartException;
}

このインターフェースの実装は、JobRepositoryから適切な JobExecution を取得してJobを実行することが期待されます。

3.6 アイテム・リーダー

ItemReader Stepのための入力データ取得を抽象化するものです。一時に1件のデータを読み込みます。ItemReaderが供給できるデータがなくなった段階で、nullを返すことでそれを表します。ItemReaderインターフェースとその種々の実装についてより詳しくは第6章「アイテム・リーダーとアイテム・ライター」を参照してください。

3.7 アイテム・ライター

ItemWriterStepの出力を抽象化するものです。一時にすべてもしくはひと塊のデータを書き出します。一般に、ライターは次に受け取ることになる入力データについて何ら関知せず、メソッドが呼び出しとともに渡された入力データについてだけしか情報を持ちません。ItemWriter インターフェースとその種々の実装についてより詳しくは第6章「アイテム・リーダーとアイテム・ライター」を参照してください。

3.8 アイテム・プロセッサー

ItemProcessor は1件のアイテムの中間処理を抽象化するものです。ItemReaderが1件単位でデータを読み込み、ItemWriterがそれらを複数件単位で書き出すのに対して、ItemProcessorはデータの変換もしくはその他の業務処理を担当します。アイテムの処理中に、当該アイテムが妥当でないと判断された場合、nullを返すことでそれが書き出されるべきでないものであることを示します。ItemProcessorインターフェースとその種々の実装についてより詳しくは第6章「アイテム・リーダーとアイテム・ライター」を参照してください。

          * * *

原典は"Spring Batch - Reference Documentation"(3.0.2.RELEASE。2014/12/29取得)の第3章「バッチのドメイン言語」です。


Spring関連の訳出記事まとめ - M12i.