Spring BatchではChunkとTaskletの2パターンの実装方式がありますが、Spring BatchのGetting StartはChunkで実装されており、Tasklet実装の例がありません。
なので、Getting StartをTasklet化してみました。
ChunkとTaskletのアーキテクチャについてはNTTデータさんがTERASOLUNAの開発ガイドラインで詳しくまとめているのでそちらが参考になるかと思います。
実施手順
Getting Startの実装
まずは、Spring BatchのGetting Startを実装します。
単純にコピペすれば動くため、Getting Startプロジェクトの実装については省略します。
なお、Tasklet化のプロジェクト構成は下図とします。
PersonTaskletの実装
Getting StartのPersonItemProcessor#processと同じ処理をTasklet#executeに実装します。
TaskletばChunkと異なり、データ読み書きのタイミングを開発者が自由に決定できます。
今回は、BatchConfigurationのWriterとReaderをDIして直接利用する方針としています。
実装例は以下となります。
public class PersonTasklet implements Tasklet {
private static final Logger log = LoggerFactory.getLogger(PersonTasklet.class);
@Autowired
ItemStreamReader<Person> reader;
@Autowired
ItemWriter<Person> writer;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
Person person = null;
ArrayList<Person> personList = new ArrayList<Person>();
try {
reader.open(chunkContext.getStepContext().getStepExecution().getExecutionContext());
while ((person = reader.read()) != null) {
String firstName = person.getFirstName().toUpperCase();
String lastName = person.getLastName().toUpperCase();
Person transformedPerson = new Person(firstName, lastName);
personList.add(person);
log.info("Converting (" + person + ") into (" + transformedPerson + ")");
}
writer.write(personList);
} finally {
reader.close();
}
return RepeatStatus.FINISHED;
}
}
Chunkではコミットインターバルの設定することで、自動で設定した処理件数ごとにコミットを実行してくれますが、Taskletは開発者がコミット処理を実装しない限り、全でデータ一括のコミットとなります。今回の実装例では、一括コミットとなっています。Taskletで中間コミットを実現したい場合は、処理件数をカウントして一定の件数でコミットを実行する処理を追加してやることで実現できます。
BatchConfigurationの修正
作成したPersonTaskletのBean定義の実装及び、BatchConfiguration#step1のstep定義をchunkからtaskletに変更します。
実装・変更内容は以下のとおりです。
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
//省略
//PersonTaskletのBean定義を追加
@Bean
public PersonTasklet tasklet() {
return new PersonTasklet();
}
//省略
//step定義のtasklet化
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet(tasklet())
.build();
}
}
あとは、実行することでGetting Startと同じ結果になればOKです。