Macchinetta Batch Framework (2.x) Development Guideline - version 2.2.0.RELEASE, 2020-6-29
> INDEX

Overview

本節では、ジョブの起動パラメータ(以降、パラメータ)の利用方法について説明する。

本機能は、チャンクモデルとタスクレットモデルとで同じ使い方になる。

パラメータは、以下のような実行環境や実行タイミングに応じてジョブの動作を柔軟に切替える際に使用する。

  • 処理対象のファイルパス

  • システムの運用日時

パラメータを与える方法は、以下のとおりである。

指定したパラメータは、Bean定義やSpring管理下のJavaで参照できる。

How to use

パラメータ変換クラスについて

Spring Batchでは、受け取ったパラメータを以下の流れで処理する。

  1. JobParametersConverterの実装クラスがJobParametersに変換する。

  2. Bean定義やSpring管理下のJavaにてJobParametersからパラメータを参照する。

パラメータ変換クラスの実装クラスについて

前述したJobParametersConverterの実装クラスは複数提供されている。 以下にそれぞれの特徴を示す。

  • DefaultJobParametersConverter

    • パラメータのデータ型を指定することができる(String、Long、Date、Doubleの4種類)。

  • JsrJobParametersConverter

    • パラメータのデータ型を指定することができない(Stringのみ)。

    • パラメータにジョブ実行を識別するID(RUN_ID)をjsr_batch_run_idという名称で自動的に付与する。

      • RUN_IDは、ジョブが実行される都度増加する。増加は、データベースのSEQUENCE(名称はJOB_SEQとなる)を利用するため、重複することがない。

      • Spring Batchでは、同じパラメータで起動したジョブは同一ジョブとして認識され、同一ジョブは1度しか実行できない、という仕様がある。 これに対し、jsr_batch_run_idという名称のパラメータを一意な値で付加することにより、別のジョブと認識する仕組みとなっている。 詳細は、Spring Batchのアーキテクチャを参照。

Spring BatchではBean定義で使用するJobParametersConverterの実装クラスを指定しない場合、DefaultJobParametersConverterが使用される。
しかし、Macchinetta Batch 2.xでは以下の理由によりDefaultJobParametersConverterは採用しない。

  • 1つのジョブを同じパラメータによって、異なるタイミングで起動することは一般的である。

  • 起動時刻のタイムスタンプなどを指定し、異なるジョブとして管理することも可能だが、それだけのためにジョブパラメータを指定するのは煩雑である。

  • DefaultJobParametersConverterはパラメータに対しデータ型を指定することができるが、型変換に失敗した場合のハンドリングが煩雑になる。

Macchinetta Batch 2.xでは、JsrJobParametersConverterを利用することで、ユーザが意識することなく自動的にRUN_IDを付与している。 この仕組みにより、ユーザから見ると同一ジョブをSpring Batchとしては異なるジョブとして扱っている。

パラメータ変換クラスの設定について

ブランクプロジェクトでは、あらかじめlaunch-context.xmlにてJsrJobParametersConverterを使用するように設定している。
そのためMacchinetta Batch 2.xを推奨設定で使用する場合はJobParametersConverterの設定を行う必要はない。

META-INF\spring\launch-context.xml
<bean id="jobParametersConverter"
      class="org.springframework.batch.core.jsr.JsrJobParametersConverter"
      c:dataSource-ref="adminDataSource" />

<bean id="jobOperator"
      class="org.springframework.batch.core.launch.support.SimpleJobOperator"
      p:jobRepository-ref="jobRepository"
      p:jobRegistry-ref="jobRegistry"
      p:jobExplorer-ref="jobExplorer"
      p:jobParametersConverter-ref="jobParametersConverter"
      p:jobLauncher-ref="jobLauncher" />

以降はJsrJobParametersConverterを利用する前提で説明する。

コマンドライン引数から与える

まず、もっとも基本的な、コマンドライン引数から与える方法について説明する。

パラメータの付与

コマンドライン引数としてCommandLineJobRunnerの第3引数以降に<パラメータ名>=<値>形式で列挙する。

パラメータの個数や長さは、Spring BatchやMacchinetta Batch 2.xにおいては制限がない。 しかし、OSにはコマンド引数の長さに制限がある。
そのため、あまりに大量の引数が必要な場合は、ファイルから標準入力へリダイレクトするパラメータとプロパティの併用などの方法を活用すること。

コマンドライン引数としてパラメータを設定する例
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID param1=abc outputFileName=/tmp/result.csv
パラメータの参照

以下のように、Bean定義またはJavaで参照することができる。

  • Bean定義で参照する

    • #{jobParameters['xxx']}で参照可能

  • Javaで参照する

    • @Value("#{jobParameters['xxx']}")で参照可能

JobParametersを参照するBeanのスコープはStepスコープでなければならない

JobParametersを参照する際は、参照するBeanのスコープをStepスコープとする必要がある。 これは、JobParametersを参照する際に、Spring Batchのlate bindingという仕組みを使用しているためである。

late bindingとはその名のとおり、遅延して値を設定することである。 Spring FrameworkのApplicationContextは、デフォルトでは各種Beanのプロパティを解決してからApplicationContextのインスタンスを生成する。 Spring BatchではApplicationContextのインスタンスを生成する時にはプロパティを解決せず、 各種Beanが必要になった際にプロパティを解決する機能をもつ。これが遅延という言葉が意味することである。 この機能により、Spring Batch自体の実行に必要なApplicationContextを生成し実行した後に、 パラメータに応じて各種Beanの振る舞いを切替えることが可能となる。

なお、StepスコープはSpring Batch独自のスコープであり、Stepの実行ごとに新たなインスタンスが生成される。 また、late bindingによる値の解決は、Bean定義においてSpEL式を用いることで可能となる。

Macchinetta Batch 2.xでは、Stepスコープの指定に@StepScopeを使用しない

Stepスコープの指定は以下のいずれかの方法で行える。

  • XMLでのBean定義で、<bean>要素にscope="step"を設定する

  • アノテーションでのBean定義で、@Componentを付与するクラスに@Scope("step")を付与する

  • JavaConfigでのBean定義で、@Beanを付与するメソッドに@StepScopeを付与する

しかしMacchinetta Batch 2.xでは、以下二つの前提によってStepスコープの指定には@StepScopeではなく、scope="step"@Scope("step")を使用する。

  • ジョブの定義は、XMLによるBean定義ファイルに記述する

  • チャンクモデル/タスクレットモデルの構成要素を実装したクラスは、@Componentを付与してBean定義する

コマンドライン引数で与えたパラメータをBean定義で参照する例
<!-- (1) -->
<bean id="reader"
      class="org.springframework.batch.item.file.FlatFileItemReader" scope="step"
      p:resource="file:#{jobParameters['inputFile']}">  <!-- (2) -->
    <property name="lineMapper">
        <!-- omitted settings -->
    </property>
</bean>
表 1. 設定内容の項目一覧
項番 説明

(1)

<bean>要素のscope属性でスコープを指定する。

(2)

参照するパラメータを指定する。

コマンドライン引数で与えたパラメータをJavaで参照する例
@Component
@Scope("step")  // (1)
public class ParamRefInJavaTasklet implements Tasklet {

    /**
     * Holds a String type value
     */
    @Value("#{jobParameters['str']}")  // (2)
    private String str;

    // omitted execute()
}
表 2. 設定内容の項目一覧
項番 説明

(1)

クラスに@Scopeアノテーションを付与してスコープを指定する。

(2)

@Valueアノテーションを使用して参照するパラメータを指定する。

ファイルから標準入力へリダイレクトする

ファイルから標準入力へリダイレクトする方法について説明する。

パラメータを定義するファイルの作成

パラメータは下記のようにファイルに定義する。

params.txt
param1=abc
outputFile=/tmp/result.csv
パラメータを定義したファイルを標準入力へリダイレクトする

コマンドライン引数としてパラメータを定義したファイルをリダイレクトする。

実行方法
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID < params.txt
パラメータの参照

パラメータの参照方法はコマンドライン引数から与える方法と同様である。

パラメータのデフォルト値を設定する

パラメータを任意とした場合、以下の形式でデフォルト値を設定することができる。

  • #{jobParameters['パラメータ名'] ?: デフォルト値}

ただし、パラメータを使用して値を設定している項目であるということは、デフォルト値もパラメータと同様に環境や実行タイミングによって異なる可能性がある。

まずは、デフォルト値をソースコード上にハードコードをする方法を説明する。 しかし、後述のパラメータとプロパティの併用を活用する方が適切なケースが多いため、合わせて参照。

デフォルト値を設定したパラメータの参照

該当するパラメータが設定されなかった場合にデフォルト値に設定した値が参照される。

コマンドライン引数で与えたパラメータをBean定義で参照する例
<!-- (1) -->
<bean id="reader"
      class="org.springframework.batch.item.file.FlatFileItemReader" scope="step"
      p:resource="file:#{jobParameters[inputFile] ?: /input/sample.csv}">  <!-- (2) -->
    <property name="lineMapper">
        <!-- omitted settings -->
    </property>
</bean>
表 3. 設定内容の項目一覧
項番 説明

(1)

<bean>要素のscope属性でスコープを指定する。

(2)

参照するパラメータを指定する。
デフォルト値に/output/result.csvを設定している。

コマンドライン引数で与えたパラメータをJavaで参照する例
@Component
@Scope("step")  // (1)
public class ParamRefInJavaTasklet implements Tasklet {

    /**
     * Holds a String type value
     */
    @Value("#{jobParameters['str'] ?: 'xyz'}")  // (2)
    private String str;

    // omitted execute()
}
表 4. 設定内容の項目一覧
項番 説明

(1)

クラスに@Scopeアノテーションを付与してスコープを指定する。

(2)

@Valueアノテーションを使用して参照するパラメータを指定する。
デフォルト値にxyzを設定している。

パラメータの妥当性検証

オペレーションミスや意図しない挙動を防ぐために、ジョブの起動時にパラメータの妥当性検証が必要となる場合もある。
パラメータの妥当性検証はSpring Batchが提供するJobParametersValidatorを活用することで実現可能である。

パラメータはItemReader/ItemProcessor/ItemWriterといった様々な場所で参照するため、 ジョブの起動直後に妥当性検証が行われる。

パラメータの妥当性を検証する方法は2つあり、検証の複雑度によって異なる。

  • 簡易な妥当性検証

    • 適用例

      • 必須パラメータが設定されていることの検証

      • 意図しないパラメータが設定されていないことの検証

    • 使用するバリデータ

      • Spring Batchが提供しているDefaultJobParametersValidator

  • 複雑な妥当性検証

    • 適用例

      • 数値の範囲検証やパラメータ間の相関チェックなどの複雑な検証

      • Spring Batchが提供しているDefaultJobParametersValidatorにて実現不可能な検証

    • 使用するバリデータ

      • JobParametersValidatorを自作で実装したクラス

簡易な妥当性検証および複雑な妥当性検証の妥当性を検証する方法についてそれぞれ説明する。

簡易な妥当性検証

Spring BatchはJobParametersValidatorのデフォルト実装として、DefaultJobParametersValidatorを提供している。
このバリデータでは設定により以下を検証することができる。

  • 必須パラメータが設定されていること

  • 必須または任意パラメータ以外のパラメータが指定されていないこと

以下に定義例を示す。

DefaultJobParametersValidatorを使用する妥当性検証の定義
<!-- (1) -->
<bean id="jobParametersValidator"
      class="org.springframework.batch.core.job.DefaultJobParametersValidator">
  <property name="requiredKeys">  <!-- (2) -->
    <list>
        <value>jsr_batch_run_id</value>  <!-- (3) -->
        <value>inputFileName</value>
        <value>outputFileName</value>
    </list>
  </property>
  <property name="optionalKeys">  <!-- (4) -->
    <list>
        <value>param1</value>
        <value>param2</value>
    </list>
  </property>
</bean>

<batch:job id="jobUseDefaultJobParametersValidator" job-repository="jobRepository">
  <batch:step id="jobUseDefaultJobParametersValidator.step01">
    <batch:tasklet ref="sampleTasklet" transaction-manager="jobTransactionManager"/>
  </batch:step>
  <batch:validator ref="jobParametersValidator"/>  <!-- (5) -->
</batch:job>
表 5. 設定内容の項目一覧
項番 説明

(1)

DefaultJobParametersValidatorのBeanを定義する。

(2)

必須パラメータはrequiredKeysに設定する。
<list>要素を使用して必須パラメータのパラメータ名を複数指定できる。

(3)

必須パラメータにjsr_batch_run_idを設定する。
Macchinetta Batch 2.xでは、DefaultJobParametersValidatorを使用する場合はこの設定が必須である。
必須となる理由は後述する。

(4)

任意パラメータはoptionalKeysに設定する。
<list>要素を使用して任意パラメータのパラメータ名を複数指定できる。

(5)

<batch:job>要素内に<batch:validator>要素を使用してジョブにバリデータを適用する。

Macchinetta Batch 2.xでは省略できない必須パラメータ

Macchinetta Batch 2.xではパラメータ変換にJsrJobParametersConverterを採用しているため、以下のパラメータが常に設定される。

  • jsr_batch_run_id

そのため、requiredKeysには、jsr_batch_run_idを必ず含めること。
詳細な説明は、パラメータ変換クラスについてを参照。

パラメータの定義例
<bean id="jobParametersValidator"
      class="org.springframework.batch.core.job.DefaultJobParametersValidator">
  <property name="requiredKeys">
    <list>
        <value>jsr_batch_run_id</value>  <!-- mandatory -->
        <value>inputFileName</value>
        <value>outputFileName</value>
    </list>
  </property>
  <property name="optionalKeys">
    <list>
        <value>param1</value>
        <value>param2</value>
    </list>
  </property>
</bean>
DefaultJobParametersValidatorを使用した場合のOKケースとNGケース

DefaultJobParametersValidatorにて検証可能な条件の理解を深めるため、検証結果がOKとなる場合とNGとなる場合の例を示す。

DefaultJobParametersValidator定義例
<bean id="jobParametersValidator"
    class="org.springframework.batch.core.job.DefaultJobParametersValidator"
    p:requiredKeys="outputFileName"
    p:optionalKeys="param1"/>
NGケース1
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID param1=aaa

必須パラメータoutputFileが設定されていないためNGとなる。

NGケース2
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID outputFileName=/tmp/result.csv param2=aaa

必須パラメータ、任意パラメータのどちらにも指定されていないパラメータparam2が設定されたためNGとなる。

OKケース1
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID param1=aaa outputFileName=/tmp/result.csv

必須および任意として指定されたパラメータが設定されているためOKとなる。

OKケース2
$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID fileoutputFilename=/tmp/result.csv

必須パラメータが設定されているためOKとなる、任意パラメータは設定されていなくてもよい。

複雑な妥当性検証

JobParametersValidatorインタフェースの実装を自作することで、 要件に応じたパラメータの検証を実現することができる。

JobParametersValidatorクラスは以下の要領で実装する。

  • JobParametersValidatorクラスを実装し、validateメソッドをオーバーライドする

  • validateメソッドは以下の要領で実装する

    • JobParametersから各パラメータを取得し検証する

      • 検証の結果がOKである場合には、何もする必要はない

      • 検証の結果がNGである場合には、JobParametersInvalidExceptionをスローする

JobParametersValidatorクラスの実装例を示す。 ここでは、strで指定された文字列の長さが、numで指定された数値以下であることを検証している。

JobParametersValidatorインタフェースの実装例
public class ComplexJobParametersValidator implements JobParametersValidator {  // (1)
    @Override
    public void validate(JobParameters parameters) throws JobParametersInvalidException {
        Map<String, JobParameter> params = parameters.getParameters();  // (2)

        String str = params.get("str").getValue().toString();  // (3)
        int num = Integer.parseInt(params.get("num").getValue().toString()); // (4)

        if(str.length() > num){
            throw new JobParametersInvalidException(
            "The str must be less than or equal to num. [str:"
                    + str + "][num:" + num + "]");  // (5)
        }
    }
}
表 6. 設定内容の項目一覧
項番 説明

(1)

JobParametersValidatorクラスを実装しvalidateメソッドをオーバーライドする。

(2)

パラメータはJobParameters型で引数として受ける。
parameters.getParameters()とすることで、Map形式で取得することでパラメータの参照が容易になる。

(3)

keyを指定してパラメータを取得する。

(4)

パラメータをint型へ変換する。String型以外を扱う場合は適宜変換を行うこと。

(5)

パラメータstrの文字列長がパラメータnumの値を超えている場合に妥当性検証結果NGとしている。

ジョブの定義例
<batch:job id="jobUseComplexJobParametersValidator" job-repository="jobRepository">
    <batch:step id="jobUseComplexJobParametersValidator.step01">
        <batch:tasklet ref="sampleTasklet" transaction-manager="jobTransactionManager"/>
    </batch:step>
    <batch:validator>  <!-- (1) -->
        <bean class="jp.co.ntt.fw.macchinetta.batch.functionaltest.ch04.jobparameter.ComplexJobParametersValidator"/>
    </batch:validator>
</batch:job>
表 7. 設定内容の項目一覧
項番 説明

(1)

<batch:job>要素内に<batch:validator>要素を使用してジョブにバリデータを適用する。

非同期起動時におけるパラメータの妥当性検証について

非同期起動方式(DBポーリングやWebコンテナ)でも、同様にジョブ起動時に検証することは可能だが、 以下のようなタイミングでジョブを起動する前に検証することが望ましい。

  • DBポーリング

    • ジョブ要求テーブルへのINSERT前

  • Webコンテナ

    • Controller呼び出し時(@Validatedを付与する)

非同期起動の場合、結果は別途確認する必要が生じるため、パラメータ設定ミスのような 場合は早期にエラーを応答し、ジョブの要求をリジェクトすることが望ましい。

また、この時の妥当性検証において、JobParametersValidatorを使う必要はない。 ジョブ要求テーブルへINSERTする機能や、Webコンテナ上のControllerは 多くの場合Spring Batchに依存していないはずであり、 JobParametersValidatorを使用するためだけにSpring Batchに依存することは避けた方がよい。

How to extend

パラメータとプロパティの併用

Spring BatchのベースであるSpring Frameworkには、プロパティ管理の機能が備わっており、 環境変数やプロパティファイルに設定した値を扱うことができる。 詳細は、Macchinetta Server 1.x 開発ガイドラインの プロパティ管理 を参照。

プロパティとパラメータを組み合わせることで、大部分のジョブに共通的な設定をプロパティファイルに行ったうえで、一部をパラメータで上書きするといったことが可能になる。

パラメータとプロパティが解決されるタイミングについて

前述のとおり、パラメータとプロパティは、機能を提供するコンポーネントが異なる。
Spring Batchはパラメータ管理の機能をもち、Spring Frameworkはプロパティ管理の機能をもつ。
この差は記述方法の差に現れている。

  • Spring Batchがもつ機能の場合

    • #{jobParameters[xxx]}

  • Spring Frameworkがもつ機能の場合

    • @Value("${xxx}")

また、それぞれの値が解決されるタイミングが異なる。

  • Spring Batchがもつ機能の場合

    • Application Contextを生成後、ジョブを実行するタイミングで設定される。

  • Spring Frameworkがもつ機能の場合

    • Application Contextの生成時に設定される。

よって、Spring Batchによるパラメータの値が優先される結果になる。
この点を念頭におくと、組み合わせる際に応用が効くため両者を区別して扱うこと。

以降、プロパティとパラメータを組み合わせて設定する方法について説明する。

環境変数による設定に加えて、コマンドライン引数で追加設定する場合

環境変数による設定に加えて、コマンドライン引数を使用してパラメータを設定する方法を説明する。
Bean定義においても同様に参照可能である。

環境変数に加えてコマンドライン引数でパラメータを設定する例
$ # Set environment variables
$ export env1=aaa
$ export env2=bbb

$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID param3=ccc outputFile=/tmp/result.csv
Javaにおいて環境変数とパラメータを参照する例
@Value("${env1}")  // (1)
private String param1;

@Value("${env2}")  // (1)
private String param2;

private String param3;

@Value("#{jobParameters['param3']")  // (2)
public void setParam3(String param3) {
    this.param3 = param3;
}
表 8. 設定内容の項目一覧
項番 説明

(1)

@Valueアノテーションを使用して参照する環境変数を指定する。
参照する際の形式は${環境変数名}である。

(2)

@Valueアノテーションを使用して参照するパラメータを指定する。
参照する際の形式は#{jobParameters['パラメータ名']である。

環境変数をデフォルトとする場合の例
$ # Set environment variables
$ export env1=aaa

$ # Execute job
$ java org.springframework.batch.core.launch.support.CommandLineJobRunner \
    JobDefined.xml JOBID param1=bbb outputFile=/tmp/result.csv
Javaにおいて環境変数をデフォルト値としてパラメータを参照する例
@Value("#{jobParameters['param1'] ?: '${env1}'}")  // (1)
public void setParam1(String param1) {
    this.param1 = param1;
}
表 9. 設定内容の項目一覧
項番 説明

(1)

環境変数をデフォルト値として@Valueアノテーションを使用して参照するパラメータを指定する。
パラメータが設定されなかった場合、環境変数の値が設定される。

誤ったデフォルト値の設定方法

以下の要領で定義した場合、コマンドライン引数からparam1を設定しない場合に、 env1の値が設定されてほしいにも関わらず、param1にnullが設定されてしまうため注意すること。

誤ったデフォルト値の設定方法例
@Value("${env1}")
private String param1;

@Value("#{jobParameters['param1']}")
public void setParam1(String param1) {
  this.param1 = param1;
}
Macchinetta Batch Framework (2.x) Development Guideline - version 2.2.0.RELEASE, 2020-6-29