https://docs.spring.io/spring-batch/4.1.x/reference/html/jsr-352.html#jsr-352
https://qiita.com/kagamihoge/items/12fbbc2eac5b8a5ac1e0 俺の訳一覧リスト
1. JSR-352 Support
Spring Batch 3.0以降はJSR-352を完全に実装しています。このセクションは仕様自体の入れ替えというより、JSR-352固有のコンセプトをSpring Batchに適用する方法について説明します。JSR-352の情報についてはJCP https://jcp.org/en/jsr/detail?id=352 を参照してください。
1.1. General Notes about Spring Batch and JSR-352
Spring BatchとJSR-352は構造的には同じです。どちらもjobはstepで作り、reader, processor, writer, listenerを持ちます。しかし、微妙に異なる箇所があります。たとえば、Spring Batchのorg.springframework.batch.core.SkipListener#onSkipInWrite(S item, Throwable t)
は引数を2つ、スキップされたアイテムとスキップ原因の例外、を取ります。JSR-352の方(javax.batch.api.chunk.listener.SkipWriteListener#onSkipWriteItem(List<Object> items, Exception ex)
)も同様に引数を2つとります。しかし、最初の引数はそのchunkの全アイテムList
で2つ目はスキップ原因のException
です。こうした差異があるため、Spring Batchでjobを実行する方法が2つ、従来通りのSpring BatchのjobかJSR-352ベースのjob、がある点には注意が必要です。Spring Batchのアーティファクト(reader, writerなど)のjobをJSR-352のJSLで設定してJsrJobOperator
で実行する場合、JSR-352のルールで動作します。なお、JSR-352で開発したバッチアーティファクトはSpring Batchのjobでは動作しない点に注意してください。
1.2. Setup
1.2.1. Application Contexts
Spring Batch内でのJSR-352ベースのjobは2つのアプリケーションコンテキストを構成します。親コンテキストは、JobRepository
, PlatformTransactionManager
などSpring Batchのインフラ部分に関連するbeanを持ち、子コンテキストは実行するjobの設定を持ちます。親コンテキストはフレームワークが提供するjsrBaseContext.xml
で定義します。このコンテキストはJSR-352-BASE-CONTEXT
システムプロパティでオーバーライドできます。
※ ベースコンテキスト(base context)はプロパティインジェクションなどのJSR-352プロセッサで処理しないため、追加処理の必要なコンポーネントはそこで設定しないでください*2。
1.2.2. Launching a JSR-352 based job
JSR-352でバッチジョブを実行する方法は大変シンプルです。ジョブを実行するのに必要なコードは以下の通りです。
JobOperator operator = BatchRuntime.getJobOperator(); jobOperator.start("myJob", new Properties());
上記は開発者にとって分かりやすいですが、落とし穴があります*3。Spring Batchは裏側でいくつかのインフラとなるbeanを初期化します。これは開発者がオーバーライド可能です。以下は初回BatchRuntime.getJobOperator()
呼び出し時に初期化される一覧です。
Bean Name | Default Configuration | Notes |
---|---|---|
dataSource | 設定値使用のApache DBCP BasicDataSource | デフォルトではHSQLDBが初期化される |
transactionManager | org.springframework.jdbc.datasource.DataSourceTransactionManager | 上記で定義するdataSource beanを参照する |
A Datasource initializer | batch.drop.script とbatch.schema.script プロパティのスクリプトを実行するために設定します。デフォルトではHSQLDBのスキーマスクリプトを実行します。この振る舞いはbatch.data.source.init プロパティでdisableに出来ます。 |
|
jobRepository | JDBCベースのSimpleJobRepository |
JobRepository は上述のデータソースとトランザクションマネージャを使用します。スキーマのテーブルプレフィクス(デフォルトBATCH_)はbatch.table.prefix プロパティで設定可能です |
jobLauncher | org.springframework.batch.core.launch.support.SimpleJobLauncher | job実行に使用 |
batchJobOperator | org.springframework.batch.core.launch.support.SimpleJobOperator | JsrJobOperator が各種機能を提供するのにこのbeanをラップする |
jobExplorer | org.springframework.batch.core.explore.support.JobExplorerFactoryBean | JsrJobOperator が提供する機能のルックアップに使用する |
jobParametersConverter | org.springframework.batch.core.jsr.JsrJobParametersConverter | JobParametersConverter のJSR-352固有実装 |
jobRegistry | org.springframework.batch.core.configuration.support.MapJobRegistry | SimpleJobOperator が使用 |
placeholderProperties | org.springframework.beans.factory.config.PropertyPlaceholderConfigure | 上述のプロパティを設定するためにbatch-${ENVIRONMENT:hsql}.properties をロードする。ENVIRONMENTはシステムプロパティ(デフォルトhsql)でSpring BatchがサポートするDBを指定可能です |
※ 上記beanのいずれもJSR-352ベースのjob実行ではオプション扱いです。どのbeanも必要に応じてカスタマイズのためにオーバライドが可能です。
1.3. Dependency Injection
JSR-352はかなりの程度Spring Batchのプログラミングモデルをベースにしています。よって、明示的に何らかのDI実装を用意する必要はありません。Spring BatchはJSR-352で定義するバッチアーティファクトのロードに3つの方法をサポートしています。
- Implementation Specific Loader - Spring BatchはSpring上で動作するので、JSR-352バッチジョブ内のSpring DIもサポートする。
- Archive Loader - JSR-352は論理名とクラス名をマッピングするbatch.xmlを定義する。このファイルを使用する場合は/META-INF/ディレクトリ内に配置する。
- Thread Context Class Loader - JSR-352はインライン完全修飾クラス名によるJSLでバッチアーティファクトの実装を指定する設定が可能です。Spring BatchはJSR-352設定のjobも同様にサポートします。
JSR-352ベースのバッチジョブでSpringのDIを使うには、Springアプリケーションコンテキストを使用するバッチアーティファクトをbeanとして設定します。bean定義後は、jobはそのbeanをbatch.xmlで定義されたかのように参照可能です。
Java Configuration
@Configuration public class BatchConfiguration { @Bean public Batchlet fooBatchlet() { FooBatchlet batchlet = new FooBatchlet(); batchlet.setProp("bar"); return batchlet; } } <?xml version="1.0" encoding="UTF-8"?> <job id="fooJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <step id="step1" > <batchlet ref="fooBatchlet" /> </step> </job>
Springコンテキストのassembly(importsなど)は、Springベースのアプリケーション同様に、JSR-352のjobでも動作しまう。JSR-352ベースのjobとの唯一の相違点は、コンテキスト定義のエントリーポイントは/META-INF/batch-jobs/のjob定義となります。
thread context class loaderの方法を使うには、refで完全修飾クラス名を渡します。この方法かbatch.xmlを使う場合、参照クラスはbean生成のために引数無しコンストラクタが必要です。
<?xml version="1.0" encoding="UTF-8"?> <job id="fooJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <step id="step1" > <batchlet ref="io.spring.FooBatchlet" /> </step> </job>
1.4. Batch Properties
1.4.1. Property Support
JSR-352は、JSLの設定方法を使用して、Job,Step,バッチアーティファクトレベルで定義するプロパティを使用可能です。バッチプロパティは以下の方法で各レベルで設定します。
<properties> <property name="propertyName1" value="propertyValue1"/> <property name="propertyName2" value="propertyValue2"/> </properties>
Properties
は各バッチアーティファクトに対して設定します。
1.4.2. @BatchProperty annotation
バッチアーティファクトのProperties
はクラスのフィールドに@BatchProperty
と@Inject
(仕様上両方のアノテーションが必要)を付与することで参照します。JSR-352の定義上、プロパティのフィールドはString型が必須です。型変換の実装と実行は開発者の責任です。
javax.batch.api.chunk.ItemReader
アーティファクトは上述のプロパティ定義と共に使用可能で以下のようにアクセスします。
public class MyItemReader extends AbstractItemReader { @Inject @BatchProperty private String propertyName1; ... }
"propertyName1"フィールドの値は"propertyValue1"になります。
1.4.3. Property Substitution
デフォルトプロパティ(Property substitution)*4は演算子とシンプルな条件付きの式を使います。一般的な使用法は#{operator['key']}
です。
サポートする演算子は以下です。
- jobParameters - job開始/再開後にjobパラメータ値にアクセス。
- jobProperties - JSLのjobレベルのプロパティにアクセス。
- systemProperties - 名前付きシステムプロパティにアクセス。
- partitionPlan - パーティション化stepのパーティーションプランの名前付きプロパティにアクセス。
#{jobParameters['unresolving.prop']}?:#{systemProperties['file.separator']}
左側が使いたい値で、右側がデフォルト値です。この例では、#{jobParameters['unresolving.prop']}
が解決不能であれば、システムプロパティfile.separator
の値となります。両方とも解決不能であれば、空文字列を返します。複数の条件を使用可能で、';'で区切ります。
1.5. Processing Models
JSR-352にはSpring Batchと同様の2つの処理モデルがあります。
- Item based processing -
javax.batch.api.chunk.ItemReader
、javax.batch.api.chunk.ItemWriter
、任意でjavax.batch.api.chunk.ItemProcessor
- Task based processing -
javax.batch.api.Batchlet
の実装。この処理モデルはorg.springframework.batch.core.step.tasklet.Tasklet
と同様。
1.5.1. Item based processing
このコンテキストにおけるitemベースの処理はItemReader
で読み込むアイテム数がセットするchunkサイズです。stepの設定には、item-count
(デフォルト10)を指定し、任意でcheckpoint-policy
をitem(デフォルト値)に設定します。
... <step id="step1"> <chunk checkpoint-policy="item" item-count="3"> <reader ref="fooReader"/> <processor ref="fooProcessor"/> <writer ref="fooWriter"/> </chunk> </step> ...
itemベースのチェックポイントを使う場合、time-limit
も使えます。指定アイテム数を処理すべきタイムリミットを設定します。タイムアウトに達すると、chunkは読み込んだitemがあったとしても、item-count
の設定に関わらず、完了します。
1.5.2. Custom checkpointing
JSR-352はstepのチェックポイント内のコミットインターバルで処理を呼び出します。上述の通りitemベースのチェックポイントはその1つです。しかし、多くの場合これは十分にロバストではありません。このため、仕様でjavax.batch.api.chunk.CheckpointAlgorithm
インタフェースの実装によりカスタムチェックポイントを作成可能です。この機能はSpring Batchのカスタムcompletion policyと同等です。CheckpointAlgorithm
の実装を使うには、checkpoint-policy
を、以下のようにstepのfooCheckpointer
でCheckpointAlgorithm
の実装を参照します。
... <step id="step1"> <chunk checkpoint-policy="custom"> <checkpoint-algorithm ref="fooCheckpointer"/> <reader ref="fooReader"/> <processor ref="fooProcessor"/> <writer ref="fooWriter"/> </chunk> </step> ...
1.6. Running a job
JSR-352ベースのjob実行のエントリーポイントはjavax.batch.operations.JobOperator
です。Spring Batchにはこのインタフェースの実装(org.springframework.batch.core.jsr.launch.JsrJobOperator
)があります。この実装クラスはjavax.batch.runtime.BatchRuntime
がロードします。JSR-352ベースのバッチジョブの起動は以下のように実装します。
JobOperator jobOperator = BatchRuntime.getJobOperator(); long jobExecutionId = jobOperator.start("fooJob", new Properties());
上記コードは以下を行います。
- ベース
ApplicationContext
の初期化 - バッチの各種機能を使えるように、フレームワークで基盤部分の初期化を行います。これはJVMごとに1回発生します。初期化コンポーネントは@EnableBatchProcessing
のそれと似ています。詳細はJsrJobOperator
のjavadocを参照してください。 - jobが要求する
ApplicationContext
のロード - 上の例では、フレームワークは/META-INF/batch-jobsのfooJob.xmlを参照し、前に解説した共有コンテキストの子コンテキストとしてロードします。 - job起動 - コンテキスト内に定義したjobを非同期に実行する。
JobExecution
のidが返される。
※ すべてのJSR-352ベースのバッチジョブは非同期に実行します。
SimpleJobOperator
でJobOperator#start
を呼ぶ場合、Spring Batchは初回実行か以前の実行のリトライかを判断します。JSR-352のJobOperator#start(String jobXMLName, Properties jobParameters)
を使う場合、フレームワークは常に新規JobInstanceを生成します(JSR-352のjobパラメータは一意性を持たない(JSR-352 job parameters are non-identifying))。jobをリスタートするには、JobOperator#restart(long executionId, Properties restartParameters)
を使用して下さい。
1.7. Contexts
JSR-352には2つのコンテキストオブジェクトがあり、jobのメタデータにアクセスするものと、バッチアーティファクトからstepにアクセスします。javax.batch.runtime.context.JobContext
とjavax.batch.runtime.context.StepContext
です。これらはstepレベルアーティファクト(Batchlet
, ItemReader
など)で利用可能で、JobContext
はjobレベルアーティファクト(JobListener
など)でも利用可能です。
カレントのスコープ内でJobContext
やStepContext
の参照を得るには、@Inject
を使います。
@Inject
JobContext jobContext;
※ @Autowire for JSR-352 contexts Springの@Autowireは上記コンテキストのインジェクションには使用出来ません。
Spring Batchでは、JobContext
とStepContext
はこれらに対応するexecutionオブジェクト(JobExecution
とStepExecution
)をラップします。StepContext#setPersistentUserData(Serializable data)
はSpring BatchのStepExecution#executionContext
に保存します。
1.8. Step Flow
JSR-352ベースのjobの内部の、stepのflowはSpring Batchのそれと同様の動作します。ただし、多少微妙に異なる点があります。
- Decision’s are steps - In a regular Spring Batch job, a decision is a state that does not have an independent StepExecution or any of the rights and responsibilities that go along with being a full step.. However, with JSR-352, a decision is a step just like any other and will behave just as any other steps (transactionality, it gets a StepExecution, etc). This means that they are treated the same as any other step on restarts as well.*5
next
属性とstep transitions - Spring Batchのjobでは、これらは同一stepで一緒に使う事が可能です。JSR-352でも同一stepで使う事が可能で、next属性が評価において優先します。- transitions要素の順序 - Spring Batchのjobでは、transition要素は最も一致するものからしないものにソートしてその順序で評価します。JSR-352のjobsはXMLで指定した順序でtransition要素を評価します。
1.9. Scaling a JSR-352 batch job
Spring Batchには4つのスケーリングの方法があります(最後の2つは複数JVMで実行)。
- Split - パラレルに複数stepを実行。
- Multiple threads - 複数スレッドで単一stepを実行。
- Partitioning - パラレル処理でデータを分割(master/slave)。
- Remote Chunking - ロジックのprocessor pieceをリモートに実行。
JSR-352はバッチジョブのスケーリングに2つのオプションがあります。両オプションとも単一JVMのみをサポートします。
- Split - Spring Batchのものと同等。
- Partitioning - Spring Batchと概念的には同等だが微妙に実装は異なる。
1.9.1. Partitioning
概念的には、JSR-352のパーティショニングはSpring Batchと同等です。処理対象の入力の識別のためにメタデータが各スレーブに渡され、スレーブはマスターに処理結果を返します。しかし、いくつか重要な違いがあります。
- Partitioned
Batchlet
- 複数スレッドで複数インスタンスのBatchlet
を動かす。各インスタンスはJSLもしくはPartitionPlan
のプロパティをそれぞれ固有で持つ。 PartitionPlan
- Spring Batchのパーティショニングでは、ExecutionContext
を各パーティションに渡します。JSR-352では、単一のjavax.batch.api.partition.PartitionPlan
をメタデータのProperties
配列と共に各パーティションに渡します。PartitionMapper
- JSR-352はパーティションメタデータの生成に2種類の方法があります。1つ目はJSL (partition properties)です。2つ目はjavax.batch.api.partition.PartitionMapper
の実装です。機能的には、このインタフェースはSpring Batchのorg.springframework.batch.core.partition.support.Partitioner
と、パーティショニングのメタデータをプログラム的に生成する、という点で似ています。StepExecutions
- Spring Batchでは、パーティションstepはmaster/slaveで動作します。JSR-352でも同一設定で動作します。ただし、スレーブのstepはofficialStepExecutions
を取得しません。このため、JsrJobOperator#getStepExecutions(long jobExecutionId)
はマスターにだけStepExecution
を返します。
※ 子StepExecutions
はジョブリポジトリには存在し、JobExplorer
およびSpring Batch Adminを介して利用可能です。
- Compensating logic - Spring Batchがstepでパーティショニングのmaster/slaveを実装する場合、
StepExecutionListeners
で何らかの補正処理を実行可能です。しかし、JSR-352のslaveは、エラー発生時の補正処理と、動的なexit status設定が可能なように、コンポーネントのコレクションを渡します。コンポーネントは以下の通りです。
Artifact Interface | Description |
---|---|
javax.batch.api.partition.PartitionCollector | スレーブstepからマスターに情報を送り返す手段の提供。スレーブスレッドごとに1インスタンス。 |
javax.batch.api.partition.PartitionAnalyzer | PartitionCollector が収集する情報と完了パーティションの結果ステータスを受け取るエンドポイント。 |
javax.batch.api.partition.PartitionReducer | パーティションstepの補正ロジックの提供。 |
1.10. Testing
JSR-352ベースのjobはすべて非同期実行なため、job完了の確認が困難です。テスト用に、Spring Batchはorg.springframework.batch.test.JsrTestUtils
を提供します。このユーティリティークラスは、jobの開始・jobのリスタート・完了待ち、が出来ます。jobが完了するとJobExecution
を返します。
*1:あんま興味無いセクションなんで他にまして訳がテキトーな点に注意してください。
*2:The base context is not processed by the JSR-352 processors for things like property injection so no components requiring that additional processing should be configured there. が原文
*3:the devil is in the details. が原文。ぐぐれば分かるが「思わぬところに落とし穴」という意味合いの慣用句。オサレに訳せなかったんで直訳
*4:正確に訳すのなら「代替プロパティ」とかになるんだろうけど。まぁええわ。
*5:よくわからんかった