Macchinetta Batch Framework (2.x) Development Guideline - version 2.5.0.RELEASE, 2024-3-28
> INDEX

バッチアプリケーションのBean定義の構成

Macchinetta Batch Framework (2.x)のバッチアプリケーションでは、Bean定義をもちいて各種設定を行う。

Spring Frameworkや、Spring Batchをはじめとする、様々なOSSを基盤としているフレームワークであるMacchinetta Batch Framework (2.x)は、Bean定義で設定できる機能も多岐に及び、これらのOSSに対する設定を行う、Bean定義も複雑なものになりやすい。

Macchinetta Batch Framework (2.x)では、Bean定義の複雑さを緩和し、管理が行いやすくなるように、役割ごとにBean定義ファイルを作成することを想定している。本ガイドラインで想定するBean定義の分類は以下の通りである。

表 1. 役割別のBean定義の分類
分類 役割 開発者のやること

アプリケーション全体のBean定義

アプリケーション全体で共通する設定をここにまとめる。これによってジョブ定義間の設定の重複を抑止する。

カスタマイズ(必要な場合)

ジョブのBean定義

業務要件にもとづくバッチ処理の定義をここにまとめる。

新規作成

非同期バッチデーモンのBean定義

非同期処理をおこなう場合の定義をここにまとめる。

カスタマイズ(必要な場合)

各Bean定義とBean定義ファイルの関係は、Bean定義の分類とBean定義ファイルの対応関係を参照のこと。

開発者がいちから作成するのはジョブのBean定義のみである。

ブランクプロジェクト(後述)では、アプリケーション全体のBean定義、非同期バッチデーモンのBean定義の定義ファイルを、初期設定済みの状態で提供する。これらは必要なときのみカスタマイズすればよい。

各Bean定義で記述する設定の詳細は、以降で説明する。

アプリケーション全体のBean定義

代表的な設定内容としては主に以下がある。

  • Macchinetta Batch Framework (2.x)を構成するOSSスタックの初期設定

    • Spring Batchの挙動設定(トランザクションの設定など)

    • MyBatis3の挙動設定(データソースからのフェッチサイズのチューニングなど)

  • 上記以外の複数のジョブに共通する設定

    • 入力チェック用バリデータの設定

    • メッセージファイルの設定

このBean定義は、他のBean定義(ジョブのBean定義、非同期バッチデーモンのBean定義)から参照される。

ジョブのBean定義

ジョブの構成要素(ジョブ、ステップ)を定義する。

詳細はジョブの作成を参照のこと。

非同期バッチデーモンのBean定義

非同期バッチデーモンの起動設定を行う。

Macchinetta Batch Framework (2.x)では、ジョブの非同期実行が可能である。テーブルに登録されているジョブの情報を監視し、非同期でジョブを起動するモジュールを非同期バッチデーモンという。

詳細は非同期実行(DBポーリング)を参照のこと。

Bean定義の記述方法

Macchinetta Batch Framework (2.x)では、Bean定義の記述方法としてJavaConfig または XMLConfig のいずれかを選択することができる。

JavaConfig/XMLConfigの説明の併記

以降、説明対象が同じであるがBean定義の媒体が異なる場合、JavaConfig/XMLConfigという形式で併記する。また、JavaConfig/XMLConfigで異なる説明が必要な箇所では、タブ切り替えを用いる。

Springの各種OSSにおけるリファレンスドキュメントでは、コード例の提示がJavaConfigしかないケースが増えているため、開発元からの正式なアナウンスは現状ないものの、今後はSpring全体として、XMLConfigよりもJavaConfigにより注力すると考えられる。

Bean定義の分類とBean定義ファイルの対応関係

各Bean定義の分類と、ブランクプロジェクトのBean定義ファイルとの関係は以下の通り。

表 2. Bean定義の分類とBean定義ファイルの対応関係
Bean定義の分類 Bean定義ファイル(JavaConfig) Bean定義ファイル(XMLConfig)

アプリケーション全体のBean定義

JobBaseContextConfig.java
LaunchContextConfig.java
TerasolunaBatchConfiguration.java

job-base-context.xml
launch-context.xml

ジョブのBean定義
(ジョブ毎にBean定義ファイル作成)

Job01Config.java

job01.xml

非同期バッチデーモンのBean定義

AsyncBatchDaemonConfig.java

async-batch-daemon.xml

上表からも明らかなように、JavaConfigのTerasolunaBatchConfiguration.javaに相当するBean定義ファイルがXMLConfigには存在しない。この理由は、Spring Batchから提供される、Bean定義をサポートする仕組み(DefaultBatchConfiguration)が、JavaConfig向けにしかないためである。

DefaultBatchConfigurationの詳細は、AppendixDefaultBatchConfigurationを参照のこと。

Macchinetta Batch Framework (2.x)では、DefaultBatchConfigurationを直接使用せず、その継承クラスTerasolunaBatchConfigurationを使用する。これは、Macchinetta Batch Framework (2.x)の動作上、DefaultBatchConfigurationの一部のBean定義のカスタマイズが必須となるためである。

TerasolunaBatchConfigurationの詳細は、AppendixTerasolunaBatchConfigurationを参照のこと。

ブランクプロジェクトとは

ブランクプロジェクトとは、各Bean定義(アプリケーション全体のBean定義、ジョブのBean定義(サンプル)、非同期バッチデーモンのBean定義)をあらかじめ行った開発プロジェクトの雛形であり、 アプリケーション開発のスタート地点である。
本ガイドラインでは、シングルプロジェクト構成のブランクプロジェクトを提供する。
構成の説明については、プロジェクトの構成を参照。

Macchinetta Server 1.xとの違い

Macchinetta Server 1.xはマルチプロジェクト構成を推奨している。 この理由は主に、以下の様なメリットを享受するためである。

  • 環境差分を吸収しやすくする

  • ビジネスロジックとプレゼンテーションを分離しやすくする

しかし、本ガイドラインではMacchinetta Server 1.xと異なりシングルプロジェクト構成としている。

これは、前述の点はバッチアプリケーションの場合においても考慮すべきだが、 シングルプロジェクト構成にすることで1ジョブに関連する資材を近づけることを優先している。
また、バッチアプリケーションの場合、 環境差分はプロパティファイルや環境変数で切替れば十分なケースが多いことも理由の1つである。

プロジェクトの作成

Maven Archetype Pluginarchetype:generateを使用して、プロジェクトを作成する方法を説明する。

作成環境の前提について

以下を前提とし説明する。

  • Java SE Development Kit 17

  • Apache Maven 3.x

    • インターネットに繋がっていること

    • インターネットにプロキシ経由で繋ぐ場合は、Mavenのプロキシ設定 が行われていること

  • IDE

    • Spring Tool Suite / Eclipse 等

プロジェクトを作成するディレクトリにて、以下のコマンドを実行する。

archetypeArtifactIdmacchinetta-batch-archetypeを指定

下記のバージョン識別子は 2.5.0.RELEASE に一部ファイルの誤配置があったため、修正した 2.5.0.1.RELEASE を指定している。
コマンドプロンプト(Windows)
C:\xxx>mvn archetype:generate ^
  -DarchetypeGroupId=com.github.macchinetta.blank ^
  -DarchetypeArtifactId=macchinetta-batch-archetype ^
  -DarchetypeVersion=2.5.0.1.RELEASE
Bash(Unix, Linux, …​)
$ mvn archetype:generate \
  -DarchetypeGroupId=com.github.macchinetta.blank \
  -DarchetypeArtifactId=macchinetta-batch-archetype \
  -DarchetypeVersion=2.5.0.1.RELEASE

archetypeArtifactIdmacchinetta-batch-xmlconfig-archetypeを指定

下記のバージョン識別子は、JavaConfig版の変更に併せて 2.5.0.1.RELEASE を指定しているが、XMLConfig版は2.5.0.RELEASE と内容は同一である。
コマンドプロンプト(Windows)
C:\xxx>mvn archetype:generate ^
  -DarchetypeGroupId=com.github.macchinetta.blank ^
  -DarchetypeArtifactId=macchinetta-batch-xmlconfig-archetype ^
  -DarchetypeVersion=2.5.0.1.RELEASE
Bash(Unix, Linux, …​)
$ mvn archetype:generate \
  -DarchetypeGroupId=com.github.macchinetta.blank \
  -DarchetypeArtifactId=macchinetta-batch-xmlconfig-archetype \
  -DarchetypeVersion=2.5.0.1.RELEASE

その後、利用者の状況に合わせて、以下を対話式に設定する。

  • groupId

  • artifactId

  • version

  • package

以下の値を設定し実行した例を示す。

表 3. ブランクプロジェクトの各要素の説明
項目名 設定例

groupId

com.example.batch

artifactId

batch

version

1.0.0-SNAPSHOT

package

com.example.batch

コマンドプロンプトでの実行例
C:\xxx>mvn archetype:generate ^
More? -DarchetypeGroupId=com.github.macchinetta.blank ^
More? -DarchetypeArtifactId=macchinetta-batch-archetype ^
More? -DarchetypeVersion=2.5.0.1.RELEASE
[INFO] Scanning for projects…​
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------

(.. omitted)

Define value for property 'groupId': com.example.batch
Define value for property 'artifactId': batch
Define value for property 'version' 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
Define value for property 'package' com.example.batch: :
Confirm properties configuration:
groupId: com.example.batch
artifactId: batch
version: 1.0.0-SNAPSHOT
package: com.example.batch
 Y: : y
[INFO] ------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: macchinetta-batch-archetype:2.5.0.1.RELEASE
[INFO] ------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example.batch
[INFO] Parameter: artifactId, Value: batch
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example.batch
[INFO] Parameter: packageInPathFormat, Value: com/example/batch
[INFO] Parameter: package, Value: com.example.batch
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.example.batch
[INFO] Parameter: artifactId, Value: batch
[INFO] Project created from Archetype in dir: C:\xxx\batch
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:02 min
[INFO] Finished at: 2019-09-03T09:24:55+09:00
[INFO] Final Memory: 13M/89M
[INFO] ------------------------------------------------------------------------
Bashでの実行例
$ mvn archetype:generate \
> -DarchetypeGroupId=com.github.macchinetta.blank \
> -DarchetypeArtifactId=macchinetta-batch-archetype \
> -DarchetypeVersion=2.5.0.1.RELEASE
[INFO] Scanning for projects…​
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------

(.. omitted)

Define value for property 'groupId': com.example.batch
Define value for property 'artifactId': batch
Define value for property 'version' 1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
Define value for property 'package' com.example.batch: :
Confirm properties configuration:
groupId: com.example.batch
artifactId: batch
version: 1.0.0-SNAPSHOT
package: com.example.batch
 Y: : y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: macchinetta-batch-archetype:2.5.0.1.RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example.batch
[INFO] Parameter: artifactId, Value: batch
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example.batch
[INFO] Parameter: packageInPathFormat, Value: com/example/batch
[INFO] Parameter: package, Value: com.example.batch
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.example.batch
[INFO] Parameter: artifactId, Value: batch
[INFO] Project created from Archetype in dir: C:\xxx\batch
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:46 min
[INFO] Finished at: 2019-09-03T02:39:57+00:00
[INFO] Final Memory: 15M/179M
[INFO] ------------------------------------------------------------------------

以上により、プロジェクトの作成が完了した。

正しく作成出来たかどうかは、ブランクプロジェクトに同梱されているサンプルジョブ(job01)を以下の要領で実行することで確認できる。

コマンドプロンプトでの実行(正しく作成できたことの確認)
C:\xxx>cd batch
C:\xxx\batch>mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
C:\xxx\batch>java -cp "lib/*;target/*" ^
org.springframework.batch.core.launch.support.CommandLineJobRunner ^
com.example.batch.jobs.Job01Config job01
Bashでの実行(正しく作成できたことの確認)
$ cd batch
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
$ java -cp 'lib/*:target/*' \
org.springframework.batch.core.launch.support.CommandLineJobRunner \
com.example.batch.jobs.Job01Config job01

以下が確認出来れば、プロジェクトの作成は成功である。

  • C:\xxx\batch\target配下にoutput.csvが作成されていること。

  • 標準出力にfollowing status: [COMPLETED]が表示されていること(以下例)。

コマンドプロンプトでの出力例
C:\xxx\batch>mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Macchinetta Batch Framework (2.x) Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(.. omitted)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 56.497 s
[INFO] Finished at: 2019-09-03T10:39:59+09:00
[INFO] Final Memory: 25M/145M
[INFO] ------------------------------------------------------------------------

C:\xxx\batch>java -cp "lib/*;target/*" ^
More? org.springframework.batch.core.launch.support.CommandLineJobRunner ^
More? com.example.batch.jobs.Job01Config job01

(.. omitted)

[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 10:41:24] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
Bashでの出力例
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Macchinetta Batch Framework (2.x) Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(.. omitted)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:39 min
[INFO] Finished at: 2019-09-03T02:43:01+00:00
[INFO] Final Memory: 27M/189M
[INFO] ------------------------------------------------------------------------

$ java -cp 'lib/*:target/*' \
> org.springframework.batch.core.launch.support.CommandLineJobRunner \
> com.example.batch.jobs.Job01Config job01

(.. omitted)

[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 02:43:11] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
コマンドプロンプトでの実行(正しく作成できたことの確認)
C:\xxx>cd batch
C:\xxx\batch>mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
C:\xxx\batch>java -cp "lib/*;target/*" ^
org.springframework.batch.core.launch.support.CommandLineJobRunner ^
META-INF/jobs/job01.xml job01
Bashでの実行(正しく作成できたことの確認)
$ cd batch
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
$ java -cp 'lib/*:target/*' \
org.springframework.batch.core.launch.support.CommandLineJobRunner \
META-INF/jobs/job01.xml job01

以下の出力が得られ、C:\xxx\batch\target配下にoutput.csvが作成されていれば、プロジェクトは正しく作成できている。

コマンドプロンプトでの出力例
C:\xxx\batch>mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Macchinetta Batch Framework (2.x) Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(.. omitted)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 56.497 s
[INFO] Finished at: 2019-09-03T10:39:59+09:00
[INFO] Final Memory: 25M/145M
[INFO] ------------------------------------------------------------------------

C:\xxx\batch>java -cp "lib/*;target/*" ^
More? org.springframework.batch.core.launch.support.CommandLineJobRunner ^
More? META-INF/jobs/job01.xml job01

(.. omitted)

[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 10:41:24] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
Bashでの出力例
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Macchinetta Batch Framework (2.x) Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(.. omitted)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:39 min
[INFO] Finished at: 2019-09-03T02:43:01+00:00
[INFO] Final Memory: 27M/189M
[INFO] ------------------------------------------------------------------------

$ java -cp 'lib/*:target/*' \
> org.springframework.batch.core.launch.support.CommandLineJobRunner \
> META-INF/jobs/job01.xml job01

(.. omitted)

[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 02:43:11] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]

プロジェクトの構成

前述までで作成したプロジェクトの構成について説明する。 プロジェクトは、以下の点を考慮した構成となっている。

  • 起動方式に依存しないジョブの実装を実現する

  • Spring BatchやMyBatisといった各種設定の手間を省く

  • 環境依存の切替を容易にする

以下に構成を示し、各要素について説明する。
(わかりやすさのため、前述のmvn archetype:generate実行時の出力をもとに説明する。)

BlankProject Structure
図 1. プロジェクトのディレクトリ構造
表 4. ブランクプロジェクトの各要素の説明
項番 説明

(1)

バッチアプリケーション全体の各種クラスを格納するrootパッケージ。

(2)

バッチアプリケーション全体に関わるBean定義ファイルを格納するディレクトリ。
Spring BatchやMyBatisの初期設定や、同期/非同期といった起動契機に依らずにジョブを起動するための設定を行っている。

(3)

非同期実行(DBポーリング)機能に関連する設定を記述したBean定義ファイル。 Ch04~Ch08以外(commonとか)の新規クラスについて、Copyrightとsinceの修正が完了しました。レビューをお願いします。

(4)

ジョブ固有のBean定義ファイルにてimportすることで、各種設定を削減するためのBean定義ファイル。
これをimportすることで、ジョブは起動契機によるBean定義の差を吸収することが出来る。

(5)

Spring Batchの挙動や、ジョブ共通の設定に対するBean定義ファイル。

(6)

Spring Batchの挙動のうち、インフラストラクチャBeanに関するBean定義ファイル。

(7)

ジョブ定義ファイルから参照される各種クラスを格納するパッケージ。
ここには、DTO、TaskletやProcessorの実装、MyBatis3のMapperインタフェースを格納する。
初期状態を参考にユーザにて自由にカスタムしてよいが、各ジョブで利用する資材をジョブごとにまとめて格納することで、 @ComponentScan@MapperScanによるスキャン範囲を最小限にする構成が望ましい。
スキャン範囲の影響や設定方法ついてはMyBatis-Springの設定を参考にすること。

(8)

ジョブ定義ファイルを格納するディレクトリ。
階層構造はジョブ個別の設計に応じて構成する。(7)のパッケージ階層と合わせておくとよい。

(9)

バッチアプリケーション全体に関わる設定ファイルで、LaunchContextConfig.java/launch-context.xmlから読み込まれる。
環境依存となるプロパティ値はここに記述する。
初期状態では、データベースの接続や、非同期実行に関する設定を記述している。
設定方法の詳細は、データベース関連の設定を参照のこと。

(10)

Logback(ログ出力)の設定ファイル。

(11)

BeanValidationを用いた入力チェックにて、エラーとなった際に表示するメッセージを定義する設定ファイル。
初期状態では、BeanValidationと、その実装であるHibernateValidatorのデフォルトメッセージを定義したうえで、 すべてコメントアウトしている。
この状態ではデフォルトメッセージを使うため、メッセージをカスタマイズしたい場合にのみ アンコメントし任意のメッセージに修正すること。
詳細は、入力チェックの表「主な比較一覧」>「エラーメッセージの設定」を参照のこと。

(12)

MyBatis3のMapperインタフェースの対となるMapper XMLファイル。

(13)

主にログ出力時に用いるメッセージを定義するプロパティファイル。

また、各ファイルの関連図を以下に示す。

Files Relation
BlankProject Structure
図 2. プロジェクトのディレクトリ構造
表 5. ブランクプロジェクトの各要素の説明
項番 説明

(1)

バッチアプリケーション全体の各種クラスを格納するrootパッケージ。

(2)

バッチアプリケーション全体に関わるBean定義ファイルを格納するディレクトリ。
Spring BatchやMyBatisの初期設定や、同期/非同期といった起動契機に依らずにジョブを起動するための設定を行っている。

(3)

非同期実行(DBポーリング)機能に関連する設定を記述したBean定義ファイル。

(4)

ジョブ固有のBean定義ファイルにてimportすることで、各種設定を削減するためのBean定義ファイル。
これをimportすることで、ジョブは起動契機によるBean定義の差を吸収することが出来る。

(5)

Spring Batchの挙動や、ジョブ共通の設定に対するBean定義ファイル。

(6)

ジョブ定義ファイルから参照される各種クラスを格納するパッケージ。
ここには、DTO、TaskletやProcessorの実装、MyBatis3のMapperインタフェースを格納する。
初期状態を参考にユーザにて自由にカスタムしてよいが、各ジョブで利用する資材をジョブごとにまとめて格納することで、 <context:component-scan><mybatis:scan>によるスキャン範囲を最小限にする構成が望ましい。
スキャン範囲の影響や設定方法ついてはMyBatis-Springの設定を参考にすること。

(7)

バッチアプリケーション全体に関わる設定ファイルで、LaunchContextConfig.java/launch-context.xmlから読み込まれる。
環境依存となるプロパティ値はここに記述する。
初期状態では、データベースの接続や、非同期実行に関する設定を記述している。
設定方法の詳細は、データベース関連の設定を参照のこと。

(8)

Logback(ログ出力)の設定ファイル。

(9)

BeanValidationを用いた入力チェックにて、エラーとなった際に表示するメッセージを定義する設定ファイル。
初期状態では、BeanValidationと、その実装であるHibernateValidatorのデフォルトメッセージを定義したうえで、 すべてコメントアウトしている。
この状態ではデフォルトメッセージを使うため、メッセージをカスタマイズしたい場合にのみ アンコメントし任意のメッセージに修正すること。
詳細は、入力チェックの表「主な比較一覧」>「エラーメッセージの設定」を参照のこと。

(10)

MyBatis3のMapperインタフェースの対となるMapper XMLファイル。

(11)

主にログ出力時に用いるメッセージを定義するプロパティファイル。

(12)

ジョブ定義ファイルを格納するディレクトリ。
階層構造はジョブ個別の設計に応じて構成する。(6)のパッケージ階層と合わせておくとよい。

また、各ファイルの関連図を以下に示す。

Files Relation

開発の流れ

ジョブを開発する一連の流れについて説明する。
ここでは、詳細な説明ではなく、大まかな流れを把握することを主眼とする。

IDEへの取り込み

生成したプロジェクトはMavenのプロジェクト構成に従っているため、 各種IDEによって、Mavenプロジェクトとしてimportする。
詳細な手順は割愛する。

アプリケーション全体の設定

ブランクプロジェクトによってあらかじめ設定されているものは説明を割愛する。以下では、ユーザの状況に応じてカスタマイズする箇所について説明する。

これら以外の設定をカスタマイズする方法については、個々の機能にて説明する。

pom.xmlのプロジェクト情報

プロジェクトのPOMには以下の情報が仮の値で設定されているため、状況に応じて設定すること。

  • プロジェクト名(name要素)

  • プロジェクト説明(description要素)

  • プロジェクトURL(url要素)

  • プロジェクト創設年(inceptionYear要素)

  • プロジェクトライセンス(licenses要素)

  • プロジェクト組織(organization要素)

データベース関連の設定

データベース関連の設定は複数箇所にあるため、それぞれを修正すること。

pom.xml
<!-- (1) -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
batch-application.properties
# (2)
# Admin DataSource settings.
admin.jdbc.driver=org.h2.Driver
admin.jdbc.url=jdbc:h2:mem:batch-admin;DB_CLOSE_DELAY=-1
admin.jdbc.username=sa
admin.jdbc.password=

# (2)
# Job DataSource settings.
#jdbc.driver=org.postgresql.Driver
#jdbc.url=jdbc:postgresql://localhost:5432/postgres
#jdbc.username=postgres
#jdbc.password=postgres
jdbc.driver=org.h2.Driver
jdbc.url=jdbc:h2:mem:batch;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=

# (3)
# Spring Batch schema initialize.
data-source.initialize.enabled=true
spring-batch.schema.script=classpath:org/springframework/batch/core/schema-h2.sql
terasoluna-batch.commit.script=classpath:org/terasoluna/batch/async/db/schema-commit.sql
com.example.batch.config.LaunchContextConfig.java
// (3)
@Bean
public DataSourceInitializer dataSourceInitializer(@Qualifier("adminDataSource") DataSource adminDataSource,
                                                   @Value("${data-source.initialize.enabled:false}") boolean enabled,
                                                   @Value("${spring-batch.schema.script}") Resource script,
                                                   @Value("${terasoluna-batch.commit.script}") Resource commitScript) {
    final DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
    dataSourceInitializer.setDataSource(adminDataSource);
    dataSourceInitializer.setEnabled(enabled);
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator(script, commitScript);
    resourceDatabasePopulator.setContinueOnError(true);
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
    return dataSourceInitializer;
}

// (4)
@Bean(destroyMethod = "close")
public BasicDataSource adminDataSource(@Value("${admin.jdbc.driver}") String driverClassName,
                                       @Value("${admin.jdbc.url}") String url,
                                       @Value("${admin.jdbc.username}") String username,
                                       @Value("${admin.jdbc.password}") String password) {
    final BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(driverClassName);
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    dataSource.setMaxTotal(10);
    dataSource.setMinIdle(1);
    dataSource.setMaxWaitMillis(5000);
    dataSource.setDefaultAutoCommit(false);
    return dataSource;
}

// (4)
@Bean(destroyMethod = "close")
public BasicDataSource jobDataSource(@Value("${jdbc.driver}") String driverClassName,
                                     @Value("${jdbc.url}") String url,
                                     @Value("${jdbc.username}") String username,
                                     @Value("${jdbc.password}") String password) {
    final BasicDataSource basicDataSource = new BasicDataSource();
    basicDataSource.setDriverClassName(driverClassName);
    basicDataSource.setUrl(url);
    basicDataSource.setUsername(username);
    basicDataSource.setPassword(password);
    basicDataSource.setMaxTotal(10);
    basicDataSource.setMinIdle(1);
    basicDataSource.setMaxWaitMillis(5000);
    basicDataSource.setDefaultAutoCommit(false);
    return basicDataSource;
}

// (5)
@Bean
public SqlSessionFactory jobSqlSessionFactory(@Qualifier("jobDataSource") DataSource jobDataSource) throws Exception {
    final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(jobDataSource);

    final org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
    configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
    configuration.setLazyLoadingEnabled(true);
    configuration.setAggressiveLazyLoading(false);
    configuration.setDefaultFetchSize(1000);
    configuration.setDefaultExecutorType(ExecutorType.REUSE);

    sqlSessionFactoryBean.setConfiguration(configuration);
    return sqlSessionFactoryBean.getObject();
}
META-INF/spring/launch-context.xml
<!-- (3) -->
<jdbc:initialize-database data-source="adminDataSource"
                          enabled="${data-source.initialize.enabled:false}"
                          ignore-failures="ALL">
    <jdbc:script location="${spring-batch.schema.script}" />
    <jdbc:script location="${terasoluna-batch.commit.script}" />
</jdbc:initialize-database>

<!-- (4) -->
<bean id="adminDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
      destroy-method="close"
      p:driverClassName="${admin.jdbc.driver}"
      p:url="${admin.jdbc.url}"
      p:username="${admin.jdbc.username}"
      p:password="${admin.jdbc.password}"
      p:maxTotal="10"
      p:minIdle="1"
      p:maxWaitMillis="5000"
      p:defaultAutoCommit="false"/>

<!-- (4) -->
<bean id="jobDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
      destroy-method="close"
      p:driverClassName="${jdbc.driver}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}"
      p:maxTotal="10"
      p:minIdle="1"
      p:maxWaitMillis="5000"
      p:defaultAutoCommit="false" />

<!-- (5) -->
<bean id="jobSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
      p:dataSource-ref="jobDataSource" >
    <property name="configuration">
        <bean class="org.apache.ibatis.session.Configuration"
            p:localCacheScope="STATEMENT"
            p:lazyLoadingEnabled="true"
            p:aggressiveLazyLoading="false"
            p:defaultFetchSize="1000"
            p:defaultExecutorType="REUSE" />
    </property>
</bean>
com.example.batch.config.AsyncBatchDaemonConfig.java
// (5)
@Bean
public SqlSessionFactory adminSqlSessionFactory(@Qualifier("adminDataSource") DataSource adminDataSource,
                                                DatabaseIdProvider databaseIdProvider) throws Exception {
    final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(adminDataSource);
    sqlSessionFactoryBean.setDatabaseIdProvider(databaseIdProvider);
    final org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
    configuration.setLocalCacheScope(LocalCacheScope.STATEMENT);
    configuration.setLazyLoadingEnabled(true);
    configuration.setAggressiveLazyLoading(false);
    configuration.setDefaultFetchSize(1000);
    configuration.setDefaultExecutorType(ExecutorType.REUSE);
    sqlSessionFactoryBean.setConfiguration(configuration);
    return sqlSessionFactoryBean.getObject();
}
META-INF/spring/async-batch-daemon.xml
<!-- (5) -->
<bean id="adminSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
      p:dataSource-ref="adminDataSource" >
    <property name="configuration">
        <bean class="org.apache.ibatis.session.Configuration"
              p:localCacheScope="STATEMENT"
              p:lazyLoadingEnabled="true"
              p:aggressiveLazyLoading="false"
              p:defaultFetchSize="1000"
              p:defaultExecutorType="REUSE" />
    </property>
</bean>
表 6. データベース関連の設定における各要素の説明
項番 説明

(1)

pom.xmlでは利用するデータベースへの接続に使用するJDBCドライバの依存関係を定義する。
初期状態ではH2 Database(インメモリデータベース)とPostgreSQLが設定されているが、必要に応じて追加削除を行うこと。

(2)

JDBCドライバの接続設定をする。
- admin.jdbc.xxxはSpring BatchやMacchinetta Batch 2.xが利用する
- jdbc.xxx~はジョブ個別が利用する

(3)

Spring BatchやMacchinetta Batch 2.xが利用するデータベースの初期化処理を実行するか否か、および、利用するスクリプトを定義する。
Spring BatchはJobRepositoryにアクセスするため、データベースが必須となる。 また、Macchinetta Batch 2.xは非同期実行(DBポーリング)にてジョブ要求テーブルにアクセスするため、 データベースが必須となる。
有効にするか否かは、以下を基準とするとよい。
- H2 Databaseを利用する場合は有効にする。無効にするとJobRepositoryジョブ要求テーブルにアクセスできずエラーになる。
- H2 Databaseを利用しない場合は事故を予防するために無効にする。

(4)

データソースの設定をする。
必要に応じて接続数等をチューニングする。

(5)

MyBatisの挙動を設定する。
必要に応じてフェッチサイズ等をチューニングする。

ジョブの作成

ジョブは、ジョブのBean定義ファイルと、そこから参照されるコンポーネントで構成される。

基本的な実装方針を下表にまとめた。

JavaConfig XMLConfig

ジョブのBean定義

@Beanを付与したメソッドで定義する。メソッド内でJobBuilderを使用する。

<batch:job>で定義する。

ステップのBean定義

@Beanを付与したメソッドで定義する。メソッド内でStepBuilderを使用する。

<batch:job>の内側で<batch:step>を定義する。

タスクレットの定義
(タスクレットモデル)

@Componentをつけたクラスとして実装し、ジョブのBean定義ファイルから@ComponentScanで読み込む。

@Componentをつけたクラスとして実装し、ジョブのBean定義ファイルから<context:component-scan>で読み込む。

ItemReader/ItemWriter
(チャンクモデル)

@Beanを付与したメソッドで定義する。

<bean>で定義する。

ItemProcessor
(チャンクモデル)

@Componentをつけたクラスとして実装し、ジョブのBean定義ファイルから@ComponentScanで読み込む。

@Componentをつけたクラスとして実装し、ジョブのBean定義ファイルから<context:component-scan>で読み込む。

Bean名(BeanID)の決定

@Beanを付与したメソッドのメソッド名

<bean><batch:job><batch:step>等のid属性に指定した名前

Beanのインジェクション方法

メソッドインジェクションを使用する

<bean>pcネームスペースや、<batch:job><batch:step>等がもつそれぞれの属性にBean名を指定する。

ネームスペースについては、以下の公式ドキュメントを参照のこと。

JavaConfigでのBeanのインジェクション時の注意事項
  • Beanのインジェクションをフィールドインジェクションやコンストラクタインジェクションで行うと、シングルトンでないBean(stepスコープなど)をインジェクションしたいときに対応できないので、使用しない。

  • 同じ型名のBeanが複数定義されている場合、引数に指定したBeanが見つからずエラーとなる。その場合は@Qualifierを付与する。

より詳細な作成方法の説明は、以下を参照。

プロジェクトのビルドと実行

プロジェクトのビルドと実行について説明する。

アプリケーションのビルド

プロジェクトのルートディレクトリに移動し、以下のコマンドを発行する。

ビルド(Windows/Bash)
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Macchinetta Batch Framework (2.x) Blank Project 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(.. omitted)

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:39 min
[INFO] Finished at: 2019-09-03T02:43:01+00:00
[INFO] Final Memory: 27M/189M
[INFO] ------------------------------------------------------------------------

これにより、以下が生成される。

  • <ルートディレクトリ>/target/[artifactId]-[version].jar

    • 作成したバッチアプリケーションのJarが生成される

  • <ルートディレクトリ>/lib/(依存Jarファイル)

    • 依存するJarファイル一式がコピーされる

試験環境や商用環境へ配備する際は、これらのJarファイルを任意のディレクトリにコピーすればよい。

環境に応じた設定ファイルの切替

プロジェクトのpom.xmlでは、初期値として以下のProfileを設定している。

pom.xmlのProfiles設定
<profiles>
    <!-- Including application properties and log settings into package. (default) -->
    <profile>
        <id>IncludeSettings</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <exclude-property/>
            <exclude-log/>
        </properties>
    </profile>

    <!-- Excluding application properties and log settings into package. -->
    <profile>
        <id>ExcludeSettings</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <exclude-property>batch-application.properties</exclude-property>
            <exclude-log>logback.xml</exclude-log>
        </properties>
    </profile>
</profiles>

ここでは、環境依存となる設定ファイルを含めるかどうかを切替ている。 この設定を活用して、環境配備の際に設定ファイルを別途配置することで環境差分を吸収することができる。 また、これを応用して、試験環境と商用環境でJarに含める設定ファイルを変えることもできる。 以下に、一例を示す。

環境ごとに設定ファイルを切替えるpom.xmlの記述例
<dependencies>
    <!-- omitted -->
    <dependency>
        <groupId>${jdbc.driver.groupId}</groupId>
        <artifactId>${jdbc.driver.artifactId}</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

<!-- omitted -->

<profiles>
    <!-- omitted -->
    <profile>
        <id>postgresql12-local</id>
        <properties>
            <jdbc.driver.groupId>org.postgresql</jdbc.driver.groupId>
            <jdbc.driver.artifactId>postgresql</jdbc.driver.artifactId>
            <!-- omitted -->
        </properties>
    </profile>
    <!-- omitted -->
    <profile>
        <id>oracle19c-local</id>
        <properties>
            <jdbc.driver.groupId>com.oracle.database.jdbc</jdbc.driver.groupId>
            <jdbc.driver.artifactId>ojdbc8</jdbc.driver.artifactId>
            <!-- omitted -->
        </properties>
    </profile>
</profiles>

なお、MavenのProfileは以下の要領で、コマンド実行時に有効化することができる。
必要に応じて、複数Profileを有効化することもできる。必要に応じて、有効活用してほしい。

MavenのProfileを有効化する例
$ mvn -P profile-1,profile-2
LocalVariableTableParameterNameDiscovererの廃止について

Spring Framework 6.1から、LocalVariableTableParameterNameDiscovererが削除された。 LocalVariableTableParameterNameDiscovererは、Spring Framework内部で、リフレクションを用いたメソッドパラメータ名を取得する処理で用いられていた。

アプリケーションでLocalVariableTableParameterNameDiscovererを用いてメソッドパラメータ名を取得する処理を実装している場合は、以下の対応が必要となる。

  • LocalVariableTableParameterNameDiscovererのかわりにStandardReflectionParameterNameDiscovererを利用する。

  • maven-compiler-plugin<configuration><parameters>true</parameters>を追加する。

pom.xmlの記述例
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven-compiler-plugin.version}</version>
    <configuration>
        <source>${java-version}</source>
        <target>${java-version}</target>
        <parameters>true</parameters> // 追加
    </configuration>
</plugin>

アプリケーションの実行

前段でビルドした結果をもとに、ジョブを実行する例を示す。
[artifactId][version]プロジェクトの作成にて設定したものに、ユーザに応じて読み替えてほしい。

コマンドプロンプト(Windows)
C:\xxx>java -cp "target\[artifactId]-[version].jar;lib\*" ^
org.springframework.batch.core.launch.support.CommandLineJobRunner ^
com.example.batch.jobs.Job01Config job01

(.. omitted)
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 10:41:24] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
Bash(Unix, Linux, …​)
$ java -cp 'target/[artifactId]-[version].jar:lib/*' \
org.springframework.batch.core.launch.support.CommandLineJobRunner \
com.example.batch.jobs.Job01Config job01

(.. omitted)
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 02:43:11] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
コマンドプロンプト(Windows)
C:\xxx>java -cp "target\[artifactId]-[version].jar;lib\*" ^
org.springframework.batch.core.launch.support.CommandLineJobRunner ^
META-INF/jobs/job01.xml job01

(.. omitted)
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 10:41:24] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 10:41:24] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]
Bash(Unix, Linux, …​)
$ java -cp 'target/[artifactId]-[version].jar:lib/*' \
org.springframework.batch.core.launch.support.CommandLineJobRunner \
META-INF/jobs/job01.xml job01

(.. omitted)
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] launched with the following parameters: [{jsr_batch_run_id=1}]
[2019/09/03 02:43:11] [main] [o.s.b.c.j.SimpleStepHandler] [INFO ] Executing step: [job01.step01]
[2019/09/03 02:43:11] [main] [o.s.b.c.l.s.TaskExecutorJobLauncher] [INFO ] Job: [FlowJob: [name=job01]] completed with the following parameters: [{jsr_batch_run_id=1}] and the following status: [COMPLETED]

これにより、<ルートディレクトリ>/target/output.csvが生成される。

javaコマンドが返却する終了コードをハンドリングする必要性

実際のシステムでは、 ジョブスケジューラからジョブを発行する際にjavaコマンドを直接発行するのではなく、 java起動用のシェルスクリプトを挟んで起動することが一般的である。

これはjavaコマンド起動前の環境変数を設定するためや、javaコマンドの終了コードをハンドリングするためである。 この、javaコマンドの終了コードのハンドリングは、以下を理由に常に行うことを推奨する。

  • javaコマンドの終了コードは正常:0、異常:1であるが、ジョブスケジューラはジョブの成功/失敗を終了コードの範囲で判断する。 そのため、ジョブスケジューラの設定によっては、javaコマンドは異常終了したのにもかかわらずジョブスケジューラは正常終了したと判断してしまう。

  • OSやジョブスケジューラが扱うことができる終了コードは有限の範囲である。

    • OSやジョブスケジューラの仕様に応じて、ユーザにて使用する終了コードの範囲を定義することが重要である。

    • 一般的に、POSIX標準で策定されている0から255の間に収めることが多い。

      • ブランクプロジェクトでは、正常:0、それ以外:255として終了コードを返却するよう設定している。

以下に、終了コードのハンドリング例を示す。

終了コードのハンドリング例
#!/bin/bash

# ..omitted.

java -cp ...
RETURN_CODE=$?
if [ $RETURN_CODE = 1 ]; then
   return 255
else
   return $RETURN_CODE
fi

Appendix

DefaultBatchConfiguration

org.springframework.batch.core.configuration.support.DefaultBatchConfigurationは、Spring Batchにより、JavaConfig向けにのみ提供されるConfigurationクラスである。

詳しくは、Spring Batchの公式リファレンス(以下)を参照のこと。

DefaultBatchConfigurationは、Spring Batchの動作に必要ないくつかのBean定義(以下)を、あらかじめ設定済みにして提供する。

  • JobRepository

  • JobExplorer

  • JobLauncher

  • JobRegistry

  • JobOperator

DefaultBatchConfigurationに相当する仕組みは、XMLConfig向けには提供されない。そのためXMLConfigでは、上述の5つのBean定義は、launch-context.xmlに記述している。

TerasolunaBatchConfiguration

TerasolunaBatchConfigurationは、DefaultBatchConfigurationのBean定義をカスタマイズするために用意されている。Bean定義のカスタマイズは、DefaultBatchConfigurationのBeanメソッドをオーバーライドすることで実現する。

TerasolunaBatchConfigurationでカスタマイズするBeanと、カスタマイズ内容は以下となる。

  • JobRepository

    • トランザクション分離レベルをSERIALIZABLEからREAD COMMITTEDに変更

  • JobOperator

    • JobParametersConverterの実装クラスを、org.springframework.batch.core.converter.DefaultJobParametersConverterからorg.terasoluna.batch.converter.JobParametersConverterImplに変更

以下は、JobRepositoryJobOperatorのカスタマイズ箇所のコードとなる。

TerasolunaBatchConfiguration.java
// omitted.
@Override
@Bean
public JobRepository jobRepository() throws BatchConfigurationException {
    JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
    jobRepositoryFactoryBean.setDataSource(
            getDataSource());
    jobRepositoryFactoryBean.setTransactionManager(
            getTransactionManager());
    jobRepositoryFactoryBean.setIncrementerFactory(getIncrementerFactory());
    jobRepositoryFactoryBean.setClobType(getClobType());
    jobRepositoryFactoryBean.setTablePrefix(getTablePrefix());
    jobRepositoryFactoryBean.setSerializer(getExecutionContextSerializer());
    jobRepositoryFactoryBean.setConversionService(getConversionService());
    jobRepositoryFactoryBean.setJdbcOperations(getJdbcOperations());
    jobRepositoryFactoryBean.setLobHandler(getLobHandler());
    jobRepositoryFactoryBean.setCharset(getCharset());
    jobRepositoryFactoryBean.setMaxVarCharLength(getMaxVarCharLength());
    jobRepositoryFactoryBean.setIsolationLevelForCreateEnum(
            Isolation.READ_COMMITTED); // (1)
    jobRepositoryFactoryBean.setValidateTransactionState(
            getValidateTransactionState());

     try {
        jobRepositoryFactoryBean.setDatabaseType(getDatabaseType());
        jobRepositoryFactoryBean.afterPropertiesSet();
        return jobRepositoryFactoryBean.getObject();

    } catch (BatchConfigurationException e) {
        throw e;
    } catch (Exception e) {
        throw new BatchConfigurationException(
                "Unable to configure the customized job repository", e);
    }
}
// omitted.
@Override
@Bean
public JobOperator jobOperator() throws BatchConfigurationException {
    JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean();
    jobOperatorFactoryBean.setTransactionManager(
            getTransactionManager());
    jobOperatorFactoryBean.setJobRepository(jobRepository());
    jobOperatorFactoryBean.setJobExplorer(jobExplorer());
    jobOperatorFactoryBean.setJobRegistry(jobRegistry());
    jobOperatorFactoryBean.setJobLauncher(jobLauncher());
    JobParametersConverterImpl jobParametersConverter = new JobParametersConverterImpl(
            getDataSource()); // (2)
    jobOperatorFactoryBean.setJobParametersConverter(
            jobParametersConverter);

    try {
        jobParametersConverter.afterPropertiesSet();
        jobOperatorFactoryBean.afterPropertiesSet();
        return jobOperatorFactoryBean.getObject();

    } catch (BatchConfigurationException e) {
        throw e;
    } catch (Exception e) {
        throw new BatchConfigurationException(
                "Unable to configure the customized job operator", e);
    }
}
// omitted.
項番 説明

(1)

トランザクション分離レベルをREAD COMMITTEDに変更する。

(2)

JobParametersConverterの実装クラスをJobParametersConverterImplに変更する。

Macchinetta Batch Framework (2.x) Development Guideline - version 2.5.0.RELEASE, 2024-3-28