Spring Batchでリーダーもライターもいらない処理をステップにする
引き続きSpring Batchの公式リファレンスからの抜粋です。今回は「タスクレット」についての記述。原典は"Spring Batch - Reference Documentation"の第5章2節「タスクレット・ステップ」(バージョンは3.0.2.RELEASE。2014/12/31取得)です。
* * *
5.2 タスクレット・ステップ
チャンク指向の処理がStep
における唯一の処理方法であるというわけではありません。Step
がストアドプロシージャの呼び出しのみからなる場合はどうなるのでしょう? こうした場合でも ItemReader
を呼び出し、その内部でストアドプロシージャの呼び出しを行わせた上でnullを返させてステップを終える、という実装方式をとることも可能ではあります。しかし実際には何もしない ItemWriter
が必要になるわけですから、ちょっと不自然なものになります。Spring BatchはこのようなシナリオのためにTaskletStep
を提供しています。
Tasklet
はexecute
という単一のメソッドしか持たないシンプルなインターフェースです。このメソッドは RepeatStatus.FINISHED
を戻り値として返すか処理が失敗したことを示す例外をスローするかしない限り、TaskletStep
により繰り返し呼び出されます。各Tasklet
の呼び出しは個別のトランザクションの中で行われます。Tasklet
実装はストアドプロシージャを呼び出すことも、スクリプトを実行することも、はたまた簡単なUPDATEステートメントを実行することも可能です。TaskletStep
を生成するには<tasklet/>要素のref属性にTasklet
オブジェクトのビーン定義を参照を指定する必要があります。<tasklet/>の子要素として<chunk/>要素を使用してはいけません:
<step id="step1"> <tasklet ref="myTasklet"/> </step>
NOTE: タスクレットが StepListener
インターフェースを実装している場合、 TaskletStep
は当該タスクレットを StepListener
として自動的に登録します。
5.2.1 タスクレット・アダプター
ItemReader
インターフェースやItemWriter
インターフェースのために用意されたアダプターと同様に、 Tasklet
インターフェースにもインターフェースと既存のクラスを橋渡しするための実装──TaskletAdapter
が用意されています。例えばレコード・セットのフラグを更新するのに便利な既存のDAOを再利用したいとします。TaskletAdapter
を使用すれば、この既存クラスのメソッドを呼び出すのに、アダプター・クラスを実装せずに済みます:
<bean id="myTasklet" class="o.s.b.core.step.tasklet.MethodInvokingTaskletAdapter"> <property name="targetObject"> <bean class="org.mycompany.FooDao"/> </property> <property name="targetMethod" value="updateFoo" /> </bean>
5.2.2 タスクレット実装例
多くのバッチ・ジョブは次のような処理を含んでいます。つまり、各種のリソースを準備するために主処理が開始されるまえに実行されなくてはならない処理や、それらのリソースをクリーンナップするために主処理が終わったあとに実行されなくてはならない処理です。大量のファイルを読み書きするジョブの場合、それらのファイルのデータを別の場所に転送したあとに、手元のファイルを削除しなくてはならないということがしばしば発生します。以下の Tasklet
実装例はまさにこのような状況のために用意されたもので、Spring Batchのサンプル・プロジェクトからの引用です:
public class FileDeletingTasklet implements Tasklet, InitializingBean { private Resource directory; public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { File dir = directory.getFile(); Assert.state(dir.isDirectory()); File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { boolean deleted = files[i].delete(); if (!deleted) { throw new UnexpectedJobExecutionException("Could not delete file " + files[i].getPath()); } } return RepeatStatus.FINISHED; } public void setDirectoryResource(Resource directory) { this.directory = directory; } public void afterPropertiesSet() throws Exception { Assert.notNull(directory, "directory must be set"); } }
上記のTasklet
実装は指定されたディレクトリ直下のファイルをすべて削除します。execute
メソッドは1回しか呼び出されない点に注意してください。あとはStep
にTasklet
への参照を設定するだけです:
<job id="taskletJob"> <step id="deleteFilesInDir"> <tasklet ref="fileDeletingTasklet"/> </step> </job> <beans:bean id="fileDeletingTasklet" class="org.springframework.batch.sample.tasklet.FileDeletingTasklet"> <beans:property name="directoryResource"> <beans:bean id="directory" class="org.springframework.core.io.FileSystemResource"> <beans:constructor-arg value="target/test-outputs/test-dir" /> </beans:bean> </beans:property> </beans:bean>
* * *
原典は"Spring Batch - Reference Documentation"の第5章2節「タスクレット・ステップ」(バージョンは3.0.2.RELEASE。2014/12/31取得)です。