WebOTX Batch Serverによるジョブの定義方法について説明します。
WebOTX Batch ServerではSpring Batchが提供するジョブ定義用のXMLの記法に従ってジョブとジョブステップを定義することができます。
ジョブとジョブステップは一つのXMLファイル内で定義することも可能ですが、実装したジョブステップの再利用性や、定義ファイルの保守性を考慮し、ジョブの定義ファイルとジョブステップの定義ファイルを分割することを推奨しています。
本章では、ジョブの定義ファイルとステップの定義ファイルを分割していることを前提に記載しています
ジョブを定義する場合、下記のようにSpring Batchが提供するxml schemaをジョブ定義ファイルで指定します。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch.xsd">
別ファイル "mystep.xml" に記載したステップ定義を読込みます。
例えば、DOMAIN_HOME/apps/<アプリケーショングループ>/classes/myjob/mystep.xmlにステップを定義した場合、
ジョブの定義内で下記のような指定を行います。
<import resource="classpath:myjob/mystep.xml"/>
この記述を行うことで、別ファイルで定義したステップの定義をジョブ定義内で参照することができます。
ステップの定義方法については、ステップの定義を参照してください。
WebOTX Batch Serverでは、ジョブのApplicationContextをFileSystemXmlApplicationContextによって初期化します。
そのため"classpath:"の指定を省略した場合、定義したパスはファイルシステムのパスとして解決を行います。
次に、各ジョブの名前と、そのジョブが実行するステップを定義します。ステップ自身の定義方法については省略しています。
<batch:job id="job1">
<batch:step id="job1-step1" parent="step1" next="job1-step2"/>
<batch:step id="job1-step2" parent="step2"/>
</batch:job>
<batch:job id="job2">
<batch:step id="job2-step1" parent="step1"/>
</batch:job>
"job1"と"job2"は異なるジョブです。"job1"では"job1-step1"を実行し、そのステップが正常に終了すると"job1-step2"を実行します。
"job2-step1"は参照するステップの定義が"job1-step1"と同一の"step1"なので、"job2-step1"は"job1-step1"と同様の処理を行うことができます。
以下のように定義することで、ステップの実行結果によってステップのフローを分岐させることができます。
<batch:job id="job3">
<batch:step id="job3-step1" parent="step1">
<batch:next on="FAILED" to="job3-recover"/>
<batch:next on="*" to="job3-step2"/>
</batch:step>
<batch:step id="job3-recover" parent="recover" next="job3-step2"/>
<batch:step id="job3-step2" parent="step2"/>
</batch:job>
"job3-step1"が失敗した場合に"job3-recover"を実行し、それ以外の場合は"job3-step2"に進みます。また"job3-recover"が正常に終了すると"job3-step2"を実行します。
フローの分岐に利用できる条件(next onに指定するパラメータ)には、ExitStatusで指定する文字列を指定することができます。
ジョブを再実行可能にするためには下記のように restartable 属性を"true"に設定する必要があります。
<batch:job id="job1" restartable="true">
<batch:step id="job1-step1" parent="step1"/>
<batch:step id="job1-step2" parent="step2"/>
</batch:job>
ジョブの定義に下記のような設定を行いリスナを登録することで、ジョブの開始・終了時に独自の処理を埋め込むことができます。
ここで登録するリスナは org.springframework.batch.core.JobExecutionListenerインタフェースを実装し、 ジョブの実行前と実行後に独自の処理をコーディングします。
<batch:job id="job1" restartable="true">
... ステップの定義 ...
<batch:listeners>
<batch:listener class="user.logic.JobExecutionListener"/>
</batch:listeners>
</batch:job>
下記のように、ジョブを定義したファイルを${DOMAIN_HOME}/apps/default/myjob/myjob.xml に格納し、対象となるWebOTX Batch Serverのドメインにデプロイすることで、定義したジョブを実行可能な状態にすることができます。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch.xsd">
<import resource="${domain.home}/apps/default/myjob/mystep.xml"/>
<batch:job id="job1">
<batch:step id="job1-step1" parent="step1"/>
<batch:step id="job1-step2" parent="step2"/>
</batch:job>
<batch:job id="job2">
<batch:step id="job2-step1" parent="step1"/>
</batch:job>
<batch:job id="job3">
<batch:step id="job3-step1" parent="step1">
<batch:next on="FAILED" to="job3-recover"/>
<batch:next on="*" to="job3-step2"/>
</batch:step>
<batch:step id="job3-recover" parent="recover" next="job3-step2"/>
<batch:step id="job3-step2" parent="step2"/>
</batch:job>
</beans>
ステップの定義では、ステップの種類とそのステップに対する設定を行います。
WebOTX Batch Serverでは、下記の中からステップの種類を定義することができます。
以下に各種類に応じた基本的なステップの定義方法について説明します。
Spring Batchが提供する部品を利用してレコード処理ステップを定義する方法について説明します。
レコード処理ステップでは、基本的に以下のような流れで処理が実行されます。
最も基本的なレコード処理ステップは、下記のように<step>、<tasklet>、<chunk>によって指定します。<chunk>の属性として ItemReader、ItemProcessor、ItemWriter の名前を指定します。 commit-interval 属性によってチャンクサイズを指定します。
<batch:step id="job1-step1" parent="step1"/>
<batch:tasklet>
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="10"/>
</batch:tasklet>
</batch:step>
ItemReader、ItemProcessor、ItemWriter の定義方法については2.2.1.3から2.2.1.7で詳細を説明します 。
レコード処理ステップの実行中に例外が発生した場合に、処理をリトライ、または、スキップするための設定を行うことができます。
<chunk>の属性にskip-limit、retry-limit によってリトライ・スキップの許容回数を指定し、<chunk>の子要素として<skippable-exceptions>や<retryable-exceptions>を追加することで指定された例外が発生した場合にリトライ・スキップの処理を行います。
<batch:step id="job1-step1" parent="step1"/>
<batch:tasklet>
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="10" skip-limit="20" retry-limit="20">
<batch:skippable-exceptions>
user.logic.SkippableException
</batch:skippable-exceptions>
<batch:retryable-exceptions>
user.logic.RetryableException
</batch:retrypable-exceptions>
</batch:chunk>
</batch:tasklet>
</batch:step>
リトライ・スキップの詳細な設定を行う場合は、下記のようなステップを定義してください。
<batch:job id="hello">
<batch:step id="sampleStep" parent="retryStep"/>
</batch:job>
<bean id="retryStep" class="org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="jobRepository" ref="jobRepository" />
<property name="itemReader" ref="itemReader"/>
<property name="itemProcessor" ref="itemProcessor"/>
<property name="itemWriter" ref="itemWriter" />
<property name="backOffPolicy" ref="backOffPolicy"/>
<property name="retryableExceptionClasses" ref="retryableExceptionClasses" />
<property name="skippableExceptionClasses" ref="skippableExceptionClasses" />
<property name="commitInterval" value="10" />
<property name="skipLimit" value="20" />
<property name="retryLimit" value="20" />
</bean>
<bean id="backOffPolicy" class="org.springframework.batch.retry.backoff.FixedBackOffPolicy">
<property name="backOffPeriod" value="5000" />
</bean>
<util:list id="retryableExceptionClasses">
<value>user.logic.RetryableException</value>
</util:list>
<util:list id="skippableExceptionClasses">
<value>user.logic.SkippableException</value>
</util:list>
上記の定義を行うことで、リトライを行う間隔を5秒に設定することができます。
org.springframework.batch.item.file.FlatFileItemReader を下記のように設定することで、ファイル用の ItemReader を定義することができます。
<bean id="fileReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="${fileReader.resource}"/>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value=","/>
<property name="quoteCharacter" value="""/> <!-- (" => ") -->
<property name="names" value="strValue, intValue"/>
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="targetType" value="webotx.batch.sample.SampleItem"/>
</bean>
</property>
</bean>
</property>
<property name="encoding" value="${fileReader.encoding}"/>
<property name="comments" value="${fileReader.comments}"/>
</bean>
resource プロパティで指定したファイルリソースを読み込み lineMapper プロパティで指定された LineMapper によってファイル内に記載された各行を解析して利用者が定義したJavaオブジェクトへのマッピングを行います。
| 要素名 | プロパティ名 | 説明 |
|---|---|---|
| org.springframework.batch.item.file.FlatFileItemReader | resource | ファイルリソースを指定します 例) file:/home/batch/input/input.csv |
| lineMapper | ファイル内の各行を利用者が定義したJavaオブジェクトにマッピングします。org.springframework.batch.item.file.LineMapper インタフェースを実装した Bean を設定します。 | |
| encoding | ファイルのエンコーディングを指定します。 | |
| comments | コメント行と判定するための文字列を指定します。 | |
| org.springframework.batch.item.file.mapping.DefaultLineMapper | lineTokenizer | org.springframework.batch.item.file.transform.DelimitedLineTokenizer
|
| fieldSetMapper | org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMappe
|
詳細は org.springframework.batch.item.file.FlatFileItemReaderのAPIリファレンスを参照し、設定できるプロパティ(setXXXXXメソッド)を確認してください。
org.springframework.batch.item.database.JdbcCursorItemReader を下記のように設定することで、データベース用の ItemReader を定義することができます。
<bean id="dbReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="${dbReader.dataSourceName}"/>
<property name="rowMapper">
<bean class="org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper">
<property name="mappedClass" value="webotx.batch.sample.SampleItem"/>
</bean>
</property>
<property name="sql" value="${dbReader.sql}"/>
</bean>
以下それぞれの要素に指定すべき代表的な設定値について説明します。
| 要素名 | プロパティ名 | 説明 |
|---|---|---|
| org.springframework.batch.item.database.JdbcCursorItemReader | dataSource | データソース名を指定します。例えば、ジョブリポジトリと同様のデータソースを利用する場合は"DefaultDataSource"を指定します。 |
| rowMapper | SQLを実行した結果として取得された ResultSet の各行を利用者が定義したJavaオブジェクトにマッピングします。org.springframework.jdbc.core.RowMapper インタフェースを実装した Bean を設定します。 | |
| sql | 実行するSQLを指定します。 | |
| org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper | name | SELECT した列の別名に指定した名前に一致するプロパティ名に値をセットする RowMapper です。 例) SELECT FIRST_NAME as name from CUSTOMER_TABLE の結果を Customer クラスの name プロパティにセットします。 |
| mappedClass | SQLを実行した結果として取得された ResultSet の各行を利用者が定義したJavaオブジェクトにマッピングします。 Bean のクラス名の FQCN を指定します。 |
詳細は org.springframework.batch.item.database.JdbcCursorItemReaderのAPIリファレンスを参照し、設定できるプロパティ(setXXXXXメソッド)を確認してください。
org.springframework.batch.item.file.FlatFileItemWriter を下記のように設定することで、ファイル用の ItemWriter を定義することができます。
<bean id="fileWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="shouldDeleteIfExists" value="${fileWriter.shouldDeleteIfExists}"/>
<property name="resource" value="${fileWriter.resource}"/>
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value=","/>
</bean>
</property>
<property name="encoding" value="${fileWriter.encoding}"/>
</bean>
以下それぞれの要素に指定すべき代表的な設定値について説明します。
| 要素名 | プロパティ名 | 説明 |
|---|---|---|
| org.springframework.batch.item.file.FlatFileItemWriter | resource | ファイルリソースを指定します。 例) file:/home/batch/output/output.csv |
| lineAggregator | Javaオブジェクトをファイルに書き出す1行に変換します。org..springframework.batch.item.file.LineAggregator インタフェースを実装した Bean を設定します。 | |
| encoding | ファイルのエンコーディングを指定します。 | |
| comments | コメント行と判定するための文字列を指定します。 | |
| org.springframework.batch.item.file.transform.DelimitedLineAggregator | FieldExtractorで分割したフィールドの配列を、指定した区切り文字で1行に連結するLineAggregatorです。 | |
| fieldExtractor | Javaオブジェクトを出力するフィールドに分割します。
|
|
| delimiter | 区切り文字を指定します。 |
詳細は org.springframework.batch.item.file.FlatFileItemWriterのAPIリファレンスを参照し、設定できるプロパティ(setXXXXXメソッド)を確認してください。
org.springframework.batch.item.database.JdbcBatchItemWriter を下記のように設定することで、 データベース用の ItemWriter を定義することができます。
<bean id="dbWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="${dbWriter.dataSourceName}"/>
<property name="itemSqlParameterSourceProvider">
<bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>
<property name="sql" value="${dbWriter.sql}"/>
</bean>
以下それぞれの要素に指定すべき代表的な設定値について説明します。
| 要素名 | プロパティ名 | 説明 |
|---|---|---|
| org.springframework.batch.item.database.JdbcBatchItemWriter | dataSource | データソースを指定します。例えば、ジョブリポジトリと同様のデータソースを利用する場合は"DefaultDataSource"を指定します。 |
| fieldExtractor | Javaオブジェクトを出力するフィールドに分割します。
|
|
| sql | 書込みを行うSQLを指定します。 |
上記の設定では、sqlプロパティに次のようなSQLを指定している場合、Item として渡されるJavaオブジェクトがもつ strValue と intValue の値が :strValue、:intValue としてSQLを実行します。
INSERT INTO WRITE_ITEMS VALUES(:strValue, :intValue)
詳細は org.springframework.batch.item.database.JdbcBatchItemWriterのAPIリファレンスを参照し、設定できるプロパティ(setXXXXXメソッド)を確認してください。
読込んだデータを加工するための ItemProcessor を下記のようなコーディングによって定義することができます。
package webotx.batch.sample;
import org.springframework.batch.item.ItemProcessor;
public class SampleItemProcessor
implements ItemProcessor<InputItem, OutputItem> {
public OutputItem process(InputItem item) throws Exception {
OutputItem out = new OutputItem();
out.setValue(item.getValue() * 100);
return out;
}
}
次のように上記クラスをステップの定義ファイルで設定します。
<bean id="itemProcessor" class="webotx.batch.sample.SampleItemProcessor"/>
ItemReader から読み取ったデータを加工する必要が無い場合、ItemProcessor として org.springframework.batch.item.support.PassThroughItemProcessor を指定することで、独自の ItemProcessor をコーディングすることなくステップを定義することができます。
<bean id="itemProcessor"
class="org.springframework.batch.item.support.PassThroughItemProcessor"/>
Javaメソッドを呼び出すだけのステップを定義する場合、 org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter クラスを指定した Bean を定義し、ステップに指定する tasklet から参照するように設定します。
<batch:step id="methodStep">
<batch:tasklet ref="methodInvokingTasklet"/>
</batch:step>
<bean id="methodInvokingTasklet"
class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetClass" value="user.logic.SampleDAO"/>
<property name="targetMethod" value="execute"/>
</bean>
コマンドを実行するだけのステップを定義する場合、 org.springframework.batch.core.step.tasklet.SystemCommandTasklet クラスを指定した Bean を定義し、<step>に指定する<tasklet>から参照するように設定します。
<batch:step id="commandStep">
<batch:tasklet ref="systemCommandTasklet"/>
</batch:step>
<bean id="systemCommandTasklet"
class="org.springframework.batch.core.step.tasklet.SystemCommandTasklet">
<property name="command" value="echo hello" />
<property name="timeout" value="5000" />
<property name="taskExecutor" ref="systemCommandTaskExecutor" />
</bean>
<bean id="systemCommandTaskExecutor"
class="org.springframework.core.task.SimpleAsyncTaskExecutor">
<property name="daemon" value="true" />
<property name="threadNamePrefix" value="CommandExecuteThread" />
</bean>
下記のような定義を行うことで、ジョブの起動時に指定したジョブパラメータをステップの定義で利用することができます。
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="#{jobParameters['input.file.name']}" />
</bean>
このような定義を行う場合は、bean の scope に"step"を指定する必要があります。
また、ジョブステップ-ジョブステップ間で情報の受け渡しを行いたい場合、ジョブ内の共有領域である JobExecutionContext に値をセットしておき、ステップの定義で参照することが可能です。
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="#{jobExecutionContext['input.file.name']}" />
</bean>
上記同様に、ステップ内で情報を共有したい場合、StepExecutionContext に値をセットしておき、ステップの定義で参照することが可能です。
<bean id="flatFileItemReader" scope="step"
class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="#{stepExecutionContext['input.file.name']}" />
</bean>
JobExecutionContext、および、StepExecutionContext への値をセットするには、 org.springframework.batch.core.StepExecutionListener を実装した Listener を定義し、その中で適切な値をセットすることができます 。
JobExecutionContext に"input.file.name"を設定する方法
public ExitStatus afterStep(StepExecution stepExecution) {
JobExecution jobExecution = stepExecution.getJobExecution();
jobExecution.getExecutionContext().putString("input.file.name", "nextInputFile.txt");
return stepExecution.getExitStatus();
}
StepExecutionContext に"input.file.name"をセットする
public ExitStatus afterStep(StepExecution stepExecution) {
stepExecution.getExecutionContext().putString("input.file.name", "nextInputFile.txt");
return stepExecution.getExitStatus();
}
このようなStepExecutionListenerを実装・登録することで、ステップの処理結果に応じたパラメータをプログラム内で決定することができます。
各ステップの定義にリスナを登録することで、ステップの開始・終了時や、レコード処理の開始・終了時に独自の処理を埋め込むことができます。
ステップの定義に下記の設定を行うことでリスナを登録します。
<batch:step id="step"/>
<batch:tasklet>
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="10"/>
<batch:listeners>
<batch:listener class="user.logic.ItemReadListener"/>
<batch:listener ref="writeListener"/>
</batch:listeners>
</batch:tasklet>
</batch:step>
<bean id="writeListener" class="user.logic.ItemWriteListener"/>
利用可能なリスナの種類として下記インタフェースが提供されています。
| リスナ | 説明 |
|---|---|
| StepExecutionListener | ステップ処理の開始・終了をハンドリングします。 |
| ChunkListener | チャンク処理の開始・終了をハンドリングします。 |
| ItemReadListener | 1件のレコード読込の開始・終了・エラーをハンドリングします。 |
| ItemProcessListener | 1件のレコード加工の開始・終了・エラーをハンドリングします。 |
| ItemWriteListener | チャンクデータ書込みの開始・終了・エラーをハンドリングします。 |
| SkipListener | ItemReader,ItemProcessor,ItemWriterの処理中にスキップしたレコードをハンドリングします。 |
WebOTX Batch Serverでは、Spring Batchにより提供される部品に加え、独自の改良を加えた部品を提供しています。
本節では、WebOTX Batch Serverが独自に提供する、ジョブの開発を助けるためのいくつかの部品について説明します。
WebOTX Batch Serverでは、ジョブの停止処理において、仕掛かり中のトランザクションを終了して強制的に停止するモードを提供しています。
この機能を有効にするためには、レコード処理ステップのリスナに強制停止リスナを追加します。
チャンク処理途中に強制停止コマンドが発行されると処理を中断できるように設定します。
<batch:step id="step"/>
<batch:tasklet>
<batch:chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="10"/>
<batch:listeners>
<batch:listener class="com.nec.webotx.batch.util.BSForceStopListener"/>
</batch:listeners>
</batch:tasklet>
</batch:step>
強制停止モードによる停止要求の有無を任意のポイントで確認し、可能な限り即時にジョブを終了させたい場合、
下記のように各ステップの定義にこのリスナを設定した上で、停止要求確認ポイントに例のようなロジックを追加します。
<step id="step">
<tasklet>
<... setting... />
<b:listeners>
<b:listener ref="stopListener"/>
</listeners>
</tasklet>
</step>
<bean id="stopListener" class="com.nec.webotx.batch.util.BSForceStopDetectionListener" />
<bean id="writer" class="some.user.package.ForceStopDetectionExample">
<property name="forceStopDetectionListener" ref="stopListener"></property>
</bean>
public class ForceStopDetectionExample {
private BSForceStopDetectionListener forceStopDetectionListener;
... accessor methods for forceStopDetectionListener ...
:
private void detectForceStop() {
if (forceStopDetectionListener.checkForceStop()) {
forceStopDetectionListener.triggerForceStop();
}
}
}
com.nec.webotx.batch.util.BSJobExecutionLogUtil クラスを利用する、または、log4jを介してジョブ実行ログに利用者のログを記録することができます。
ジョブ実行ログは、ジョブ毎のファイルに記録され、ジョブの実行コマンドの標準出力にも表示できる便利なログです。
BSJobExecutionLogUtil クラスは、下記のようなItemProcessorを定義することで、ItemReaderによって読込んだItemオブジェクトの内容を、ジョブ実行ログに出力するItemProcessorとして利用することも可能です。
<bean id="processor"
class="org.springframework.batch.item.adapter.ItemProcessorAdapter">
<property name="targetObject">
<bean class="com.nec.webotx.batch.util.BSJobExecutionLogUtil"/>
</property>
<property name="targetMethod" value="info"/>
</bean>
同様の方法でItemWriterAdapterへセットすることで、ログ出力のみを行うItemWriterも簡単に定義できます。
また、例えば以下のようにして、プログラム内から利用することもできます。
Log log = BSJobExecutionLogUtil.getLogger();
...
log.info("利用者メッセージ");
WebSAM JobCenterでは、ジョブネット内における前段の単位ジョブの結果を次の単位ジョブの入力にできる変数継承機能が提供されています。
この変数継承機能をBSで利用するためには、下記のような定義をジョブに追加してください。
<batch:job id="job">
<batch:step id="step">
... ステップの定義 ...
</batch:step>
...
<batch:listeners>
<batch:listener ref="exportVarListener">
</batch:listeners>
</batch:job>
<bean id="exportVarListener" class="com.nec.webotx.batch.util.ExportVariableJobExecutionListener">
<property name="properties" ref="variables"/>
</bean>
<bean id="variables" class="java.util.Properties">
<constructor-arg>
<props>
<prop key="AAAAA">BBBBB</prop> <!-- デフォルト値 -->
</props>
</constructor-arg>
</bean>
<bean id="userLogic" class=".....">
...
<property name="exportVars" ref="variables"/>
...
</bean>
この定義により"userLogic"により参照・変更されたProperties("variables")がジョブの終了時にジョブ実行コマンドの標準出力に下記の出力が記録されます。
... EXPORTVAR AAAAA=BBBBB ...利用者により追加変更された変数... EXPORTVAR ...
JobCenterの変数継承機能は上記のように"EXPORTVAR"で囲まれた範囲のKEY=VALUEを継承すべき変数として認識します。