TERASOLUNA Batch Framework for Java (5.x) Development Guideline - version 5.8.0.RELEASE, 2026-3-31, commit-id:f8c098e
> INDEX

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

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

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

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

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

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

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

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

ジョブのBean定義

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

新規作成

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

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

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

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

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

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

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

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

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

  • TERASOLUNA Batch Framework for Java (5.x)を構成するOSSスタックの初期設定

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

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

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

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

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

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

ジョブのBean定義

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

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

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

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

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

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

Bean定義の記述方法

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

JavaConfig/XMLConfigの説明の併記

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

XMLConfigが将来的に利用できなくなる可能性についての注意事項

Spring Batch 6.0.0から、XMLConfigを用いたBean定義は非推奨となっているため、今後新たにブランクプロジェクトから開発プロジェクトを新規作成する場合、Bean定義にはJavaConfigを用いること。

一方、現在開発プロジェクトでXMLConfigのBean定義を利用している場合、XMLConfigの非推奨化に伴い今後のリリースではXMLConfigのスキーマ定義(XSD)がアップデートされないことから、更新差分については部分的にJavaConfigのインポートが必要となる場合があるなどBean定義の管理が煩雑化する恐れがあるため、この機会にJavaConfigへの移行を推奨する。

JavaConfigに処理内容を直接実装しない

JavaConfigにItemReader/ItemWriter/ItemProcessor/Taskletの実装に含まれるビジネスロジックやデータの変換や検証、処理分岐を直接記述してはならない。

JavaConfigに処理内容を直接実装すると、業務処理が設定クラスに含まれることになり、JavaConfig自体がテスト対象となる。
そのため、@Configuration/@Beanや外部設定に依存しやすく、実装部分のテストでも毎回ジョブの起動が必要になり、JavaConfigではないクラスと比較して単体テストの記述が非常に困難になる。

JavaConfigに処理内容を直接実装すると、以下のような問題が発生しやすい。

  • 業務処理が十分にテストされない

    • JavaConfigは一般的に設定と認識されやすく、テスト対象から除外されやすい。
      そのため、JavaConfig内に業務処理を記述すると、意図せず未テストコードが発生するリスクが高まる。

  • 再利用性が低下する

    • Bean定義(スコープ、依存関係、プロパティ値など)の都合に実装が引きずられ、同様の処理でもジョブやステップごとに専用実装を用意しがちになり、再利用しづらくなる。

そのため、ItemReader/ItemWriter/ItemProcessor/Taskletの実装はJavaConfigとは別のクラスに実装し、JavaConfigからはそれらのクラスをBeanとして登録する形で利用すること。

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定義をサポートする仕組み(JdbcDefaultBatchConfiguration)が、JavaConfig向けにしかないためである。

JdbcDefaultBatchConfigurationの詳細は、AppendixJdbcDefaultBatchConfigurationを参照のこと。

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

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

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

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

TERASOLUNA Server 5.xとの違い

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

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

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

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

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

プロジェクトの作成

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

作成環境の前提について

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

  • Java SE Development Kit 17

  • Apache Maven 3.x

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

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

  • IDE

    • Spring Tool Suite / Eclipse 等

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

JavaConfig

archetypeArtifactIdterasoluna-batch-archetypeを指定

コマンドプロンプト(Windows)
C:\xxx>mvn archetype:generate ^
  -DarchetypeGroupId=org.terasoluna.batch ^
  -DarchetypeArtifactId=terasoluna-batch-archetype ^
  -DarchetypeVersion=5.8.0.RELEASE
Bash(Unix, Linux, …​)
$ mvn archetype:generate \
  -DarchetypeGroupId=org.terasoluna.batch \
  -DarchetypeArtifactId=terasoluna-batch-archetype \
  -DarchetypeVersion=5.8.0.RELEASE
XMLConfig

archetypeArtifactIdterasolunba-batch-xmlconfig-archetypeを指定

コマンドプロンプト(Windows)
C:\xxx>mvn archetype:generate ^
  -DarchetypeGroupId=org.terasoluna.batch ^
  -DarchetypeArtifactId=terasoluna-batch-xmlconfig-archetype ^
  -DarchetypeVersion=5.8.0.RELEASE
Bash(Unix, Linux, …​)
$ mvn archetype:generate \
  -DarchetypeGroupId=org.terasoluna.batch \
  -DarchetypeArtifactId=terasoluna-batch-xmlconfig-archetype \
  -DarchetypeVersion=5.8.0.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=org.terasoluna.batch ^
More? -DarchetypeArtifactId=terasoluna-batch-archetype ^
More? -DarchetypeVersion=5.8.0.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: terasolua-batch-archetype:5.8.0.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=org.terasoluna.batch \
> -DarchetypeArtifactId=terasoluna-batch-archetype \
> -DarchetypeVersion=5.8.0.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: terasoluna-batch-archetype:5.8.0.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)を以下の要領で実行することで確認できる。

JavaConfig
コマンドプロンプトでの実行(正しく作成できたことの確認)
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

CommandLineJobRunnerは現在非推奨となっているが、TERASOLUNA Batch 5.xでの利用方針については非推奨であるCommandLineJobRunnerを利用する理由を参照されたい。

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

  • 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 TERASOLUNA Batch Framework for Java (5.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 TERASOLUNA Batch Framework for Java (5.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]
XMLConfig
コマンドプロンプトでの実行(正しく作成できたことの確認)
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

CommandLineJobRunnerは現在非推奨となっているが、TERASOLUNA Batch 5.xでの利用方針については非推奨であるCommandLineJobRunnerを利用する理由を参照されたい。

以下の出力が得られ、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 TERASOLUNA Batch Framework for Java (5.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 TERASOLUNA Batch Framework for Java (5.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実行時の出力をもとに説明する。)

JavaConfig
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
XMLConfig
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
JavaConfig
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.setMaxWait(Duration.ofMillis(5000L));
    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.setMaxWait(Duration.ofMillis(5000L));
    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();
}
XMLConfig
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:defaultAutoCommit="false">
    <property name="maxWait">
        <bean class="java.time.Duration" factory-method="ofMillis">
            <constructor-arg name="millis" type="long" value="5000" />
        </bean>
    </property>
</bean>

<!-- (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:defaultAutoCommit="false">
    <property name="maxWait">
        <bean class="java.time.Duration" factory-method="ofMillis">
            <constructor-arg name="millis" type="long" value="5000" />
        </bean>
    </property>
</bean>

<!-- (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>
JavaConfig
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();
}
XMLConfig
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やTERASOLUNA Batch 5.xが利用する
- jdbc.xxx~はジョブ個別が利用する

(3)

Spring BatchやTERASOLUNA Batch 5.xが利用するデータベースの初期化処理を実行するか否か、および、利用するスクリプトを定義する。
Spring BatchはJobRepositoryにアクセスするため、データベースが必須となる。 また、TERASOLUNA Batch 5.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でメソッドインジェクションを使用する理由

JavaConfigでは同じBean定義クラス内に様々なスコープのBeanを定義することができる。一方でコンストラクタやフィールドインジェクションを使用した場合、JavaConfigクラスのインスタンス生成時に行われるただ一度のインジェクションで固定されてしまうため、step スコープなどのように、シングルトンではないBeanのインジェクションには対応できなくなる。

このため、JavaConfigでBeanのインジェクションを行う場合、@Beanアノテーションが付与されたメソッドの引数を使用し、コンストラクタやフィールドに対するインジェクションを使用しないこと。

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

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

同じ型をもつBeanが複数ある場合は@Qualifierアノテーションを付与する(JavaConfigのみ)

JavaConfigでは、デフォルトではBeanの特定は型名で行われる。そのため、同じ型をもつBeanが複数定義されていると、Beanが特定できずエラーとなる。エラーを回避するために、一意なBeanIDを明示する@Qualifierアノテーションを付与する。

なお、TERASOLUNA Batch 5.xでは、次に紹介するケースで@Qualifierアノテーションの付与が必須となる。

データソース、トランザクションマネージャをインジェクションするとき

TERASOLUNA Batch 5.xでは、データソース、トランザクションマネージャは、同じ型をもつ複数のBean定義が存在する。そのため、これらのBeanをインジェクションするときは、@QualifierアノテーションでBeanIDを指定しBeanを特定する必要がある。

具体的には以下のBeanが対象となる。

BeanID 用途

adminDataSource

Spring BatchやTERASOLUNA Batch 5.xが利用するデータソース

org.apache.commons.dbcp2.BasicDataSource

jobDataSource

ジョブが利用するデータソース

adminTransactionManager

Spring BatchやTERASOLUNA Batch 5.xが利用するトランザクションマネージャ

org.springframework.transaction.PlatformTransactionManager

jobTransactionManager

ジョブが利用するトランザクションマネージャ

以下はジョブ定義でjobTransactionManager@Qualifierアノテーション付きでインジェクションする例となる。

@Bean
public Step exampleStep(JobRepository jobRepository,
                   @Qualifier("jobTransactionManager") PlatformTransactionManager transactionManager, // (1)
                   ItemReader reader,
                   ItemProcessor processor,
                   ItemWriter writer) {
    return new StepBuilder("exampleJob.exampleStep",
            jobRepository)
            .<ItemReader, ItemWriter> chunk(10, transactionManager)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
}
表 7. jobTransactionManagerのインジェクション
項番 説明

(1)

Beanメソッドの引数transactionManager@Qualifierアノテーションを付与する。その際、BeanID(jobTransactionManager)を指定する。

非推奨であるSimpleStepBuilderを利用する理由

前述のジョブ定義例では StepBuilder#chunk(int chunkSize, PlatformTransactionManager transactionManager) を利用してステップを定義しているが、Spring Batchバージョン6から StepBuilder#chunk(int chunkSize, PlatformTransactionManager transactionManager) は非推奨となっており、代替として StepBuilder#chunk(int chunkSize) の利用が推奨されている。
これは、 StepBuilder#chunk(int chunkSize, PlatformTransactionManager transactionManager) が返す SimpleStepBuilder クラスが非推奨となったためであり、 StepBuilder#chunk(int chunkSize) が返す ChunkOrientedStepBuilder に代替されたためである。
しかし、TERASOLUNA Batch Framework for Java (5.x)のバージョン5.8.0.RELEASEでは、以下の理由により引き続き SimpleStepBuilder を利用する。

  • Spring Batchバージョン6.0.2での ChunkOrientedStepBuilder に関するIssueで、いくつかの不具合が報告されている。

    • チャンクトランザクションがロールバックした場合でも ItemStream の状態が更新され、再開時にデータ欠損が発生する可能性がある。 #5182

    • ステップがマルチスレッドとして構成されている場合、 @StepScope で定義された ItemProcessor がワーカースレッド内で正しく解決されない。 #5183

    • ChunkOrientedStep#doExecute() がトランザクション境界外で StepExecution を更新するため、メタデータの不整合が発生する可能性がある。 #5199

次回リリースで ChunkOrientedStepBuilder への移行と、付随する各機能の利用方法が変更される可能性がある点に注意されたい。

ジョブのフロー制御や並列処理で複数のステップを定義するとき

フロー制御や並列処理では複数のステップを定義するため、型(org.springframework.batch.core.step.Step)が重複する。ジョブのBean定義にステップをインジェクションする際に、@Qualifierアノテーションを付与する。

以下は複数のステップを@Qualifierアノテーション付きでインジェクションする例となる。

@Bean
public Step stepA(JobRepository jobRepository,
                  SequentialFlowTasklet tasklet,
                  ChangeExitCodeReturnListener listener,
                  @Qualifier("jobTransactionManager") PlatformTransactionManager transactionManager) {
  // omitted.
}

@Bean
public Step stepB(JobRepository jobRepository,
                  SequentialFlowTasklet tasklet,
                  ChangeExitCodeReturnListener listener,
                  @Qualifier("jobTransactionManager") PlatformTransactionManager transactionManager) {
  // omitted.
}

@Bean
public Step stepC(JobRepository jobRepository,
                  SequentialFlowTasklet tasklet,
                  ChangeExitCodeReturnListener listener,
                  @Qualifier("jobTransactionManager") PlatformTransactionManager transactionManager) {
  // omitted.
}

@Bean
public Job jobConditionalFlow(JobRepository jobRepository,
                              @Qualifier("stepA") Step stepA, // (1)
                              @Qualifier("stepB") Step stepB, // (2)
                              @Qualifier("stepC") Step stepC) { // (3)
  // omitted.
}
表 8. jobTransactionManagerのインジェクション
項番 説明

(1)

Beanメソッドの引数stepA@Qualifierアノテーションを付与する。その際、BeanID(stepA)を指定する。

(2)

Beanメソッドの引数stepB@Qualifierアノテーションを付与する。その際、BeanID(stepB)を指定する。

(3)

Beanメソッドの引数stepC@Qualifierアノテーションを付与する。その際、BeanID(stepC)を指定する。

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

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

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

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

ビルド(Windows/Bash)
$ mvn clean dependency:copy-dependencies -DoutputDirectory=lib package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building TERASOLUNA Batch Framework for Java (5.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>postgresql16-local</id>
        <properties>
            <jdbc.driver.groupId>org.postgresql</jdbc.driver.groupId>
            <jdbc.driver.artifactId>postgresql</jdbc.driver.artifactId>
            <!-- omitted -->
        </properties>
    </profile>
    <!-- omitted -->
    <profile>
        <id>oracle23c-local</id>
        <properties>
            <jdbc.driver.groupId>com.oracle.database.jdbc</jdbc.driver.groupId>
            <jdbc.driver.artifactId>ojdbc17</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]プロジェクトの作成にて設定したものに、ユーザに応じて読み替えてほしい。

JavaConfig
コマンドプロンプト(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]

CommandLineJobRunnerは現在非推奨となっているが、TERASOLUNA Batch 5.xでの利用方針については非推奨であるCommandLineJobRunnerを利用する理由を参照されたい。

XMLConfig
コマンドプロンプト(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]

CommandLineJobRunnerは現在非推奨となっているが、TERASOLUNA Batch 5.xでの利用方針については非推奨であるCommandLineJobRunnerを利用する理由を参照されたい。

これにより、<ルートディレクトリ>/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

JdbcDefaultBatchConfiguration

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

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

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

  • JobRepository

  • JobOperator

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

TerasolunaBatchConfiguration

TerasolunaBatchConfigurationは、JdbcDefaultBatchConfigurationのBean定義を、TERASOLUNA Batch 5.xの機能のために拡張している。その中でも一部機能については、Bean定義のカスタマイズが必要であるため、JdbcDefaultBatchConfigurationBean定義メソッドをオーバーライドすることで実現している。

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

  • JobRepository

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

  • JobOperator

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

  • TaskExecutor

    • デフォルトの実装クラスとしてorg.springframework.core.task.SyncTaskExecutorを定義

    • 非同期実行時にBean定義の上書きを容易にするために明示的に定義している

  • JobRegistry

    • org.springframework.batch.core.configuration.support.MapJobRegistryを実装クラスとして定義

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

TerasolunaBatchConfiguration.java
// omitted.
@Bean
@Override
public JobRepository jobRepository() throws BatchConfigurationException {
    JdbcJobRepositoryFactoryBean jobRepositoryFactoryBean = new JdbcJobRepositoryFactoryBean();
    try {
        jobRepositoryFactoryBean.setDataSource(getDataSource()); // get and set adminDataSource
        jobRepositoryFactoryBean.setTransactionManager(getTransactionManager()); // get and set adminTransactionManager
        jobRepositoryFactoryBean.setDatabaseType(getDatabaseType());
        jobRepositoryFactoryBean.setIncrementerFactory(getIncrementerFactory());
        jobRepositoryFactoryBean.setJobKeyGenerator(getJobKeyGenerator());
        jobRepositoryFactoryBean.setClobType(getClobType());
        jobRepositoryFactoryBean.setTablePrefix(getTablePrefix());
        jobRepositoryFactoryBean.setSerializer(getExecutionContextSerializer());
        jobRepositoryFactoryBean.setConversionService(getConversionService());
        jobRepositoryFactoryBean.setJdbcOperations(getJdbcOperations());
        jobRepositoryFactoryBean.setCharset(getCharset());
        jobRepositoryFactoryBean.setMaxVarCharLength(getMaxVarCharLength());
        jobRepositoryFactoryBean.setIsolationLevelForCreateEnum(Isolation.READ_COMMITTED); // changed from SERIALIZABLE
        jobRepositoryFactoryBean.setValidateTransactionState(getValidateTransactionState());
        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.
@Bean
@Override
public JobOperator jobOperator(JobRepository jobRepository) throws BatchConfigurationException {
    JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean();
    jobOperatorFactoryBean.setJobRepository(jobRepository);
    jobOperatorFactoryBean.setJobRegistry(jobRegistry());
    jobOperatorFactoryBean.setTransactionManager(getTransactionManager());
    jobOperatorFactoryBean.setObservationRegistry(getObservationRegistry());
    JobParametersConverterImpl jobParametersConverter = new JobParametersConverterImpl(
            getDataSource());
    jobOperatorFactoryBean.setJobParametersConverter(
            jobParametersConverter); // changed from JobParametersConverterImpl
    jobOperatorFactoryBean.setTaskExecutor(taskExecutor());
    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);
    }
}

@Bean
public TaskExecutor taskExecutor() {
    return new SyncTaskExecutor(); // (3)
}

@Bean
public JobRegistry jobRegistry() {
    return new MapJobRegistry(); // (4)
}
// omitted.
項番 説明

(1)

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

(2)

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

(3)

シングルスレッドで同期的にジョブを起動するためのTaskExecutorとしてSyncTaskExecutorを定義する。
非同期実行を行う場合は、別途設定クラスで同名のBeanを定義して上書きすることで、ThreadPoolTaskExecutorを利用する。

(4)

JobRegistryの実装クラスとしてMapJobRegistryを定義する。
非同期実行で使用するautomaticJobRegistrarのBean定義からも参照されるため、明示的に定義している。

非推奨であるJobOperatorFactoryBean#setJobParametersConverter()を利用する理由

JobOperatorFactoryBean#setJobParametersConverter() はSpring Batchバージョン6から非推奨となっている。
しかし、TERASOLUNA Batch Framework for Java (5.x)のバージョン5.8.0.RELEASEでは、以下の理由により引き続き JobOperatorFactoryBean#setJobParametersConverter() を利用する。

JobOperatorFactoryBean#setJobParametersConverter() は、パラメータ変換クラスについて で紹介されている JobParametersConverter のカスタム実装に不可欠である。
また、Spring Batchバージョン6以降では、 JobOperatorFactoryBean#setJobParametersConverter() の代替は提供されていない。

このため、TERASOLUNA Batch Framework for Java (5.x)のバージョン5.8.0.RELEASEでは、現在Spring Batchで非推奨とされている JobOperatorFactoryBean#setJobParametersConverter() を引き続き利用する前提としている点に留意されたい。
加えて、次回リリースで JobOperatorFactoryBean#setJobParametersConverter() の削除と付随する各機能の利用方法が変更される可能性がある点にも注意されたい。

TERASOLUNA Batch Framework for Java (5.x) Development Guideline - version 5.8.0.RELEASE, 2026-3-31, commit-id:f8c098e