https://docs.spring.io/spring-batch/4.1.x/reference/html/whatsnew.html#whatsNew
https://qiita.com/kagamihoge/items/12fbbc2eac5b8a5ac1e0 俺の訳一覧リスト
1. What’s New in Spring Batch 4.1
Spring Batch 4.1 releaseは以下の新機能があります。
@SpringBatchTest
バッチのコンポーネントテスト用のアノテーション。@EnableBatchIntegration
remote chunking and partitioning configuration用のアノテーション- JSONフォーマット用の
JsonItemReader
とJsonFileItemWriter
- Bean Validation APIでbeanをvalidateする機能の追加
- JSR-305アノテーションの機能追加
FlatFileItemWriterBuilder
APIの機能強化
@SpringBatchTestアノテーション
Spring Batchにはバッチコンポーネントテスト用のユーティリティクラス(JobLauncherTestUtils
とJobRepositoryTestUtils
)とtest execution listeners(StepScopeTestExecutionListener
とJobScopeTestExecutionListener
)があります。しかし、これらユーティリティを使用するには、明示的なbean設定が必要です。今回リリースで導入する@SpringBatchTest
は自動的にユーティリティのbeanとリスナをテストコンテキストに追加してautowiringで利用可能にします。
@RunWith(SpringRunner.class) @SpringBatchTest @ContextConfiguration(classes = {JobConfiguration.class}) public class JobTest { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Autowired private JobRepositoryTestUtils jobRepositoryTestUtils; @Before public void clearMetadata() { jobRepositoryTestUtils.removeJobExecutions(); } @Test public void testJob() throws Exception { // given JobParameters jobParameters = jobLauncherTestUtils.getUniqueJobParameters(); // when JobExecution jobExecution = jobLauncherTestUtils.launchJob(jobParameters); // then Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } }
このアノテーションについては、Unit Testingを参照してください。
1.2. @EnableBatchIntegration Annotation
remote chunking jobの設定にはいくつかのbean定義が必要です。
- メッセージングミドルウェア(JMS, AMQPなど)からコネクションを得るためのコネクションファクトリ
MessagingTemplate
マスタからワーカーにリクエストを送信してその戻りの処理- メッセージングミドルウェアからメッセージを得るSpring Integrationの入出力チャネル
- 処理と書き込みをするワーカーにデータのchunkを送信する、マスター側のitem writer(
ChunkMessageChannelItemWriter
) - マスターからデータを受信する、ワーカー側のメッセージリスナー(
ChunkProcessorChunkHandler
)
これは一見するだけで設定が面倒なのが分かります。今回リリースではAPIに加えて設定を簡易化するための@EnableBatchIntegration
も追加しています。以下はこのアノテーションとAPIの使用例です。
@Configuration @EnableBatchProcessing @EnableBatchIntegration public class RemoteChunkingAppConfig { @Autowired private RemoteChunkingMasterStepBuilderFactory masterStepBuilderFactory; @Autowired private RemoteChunkingWorkerBuilder workerBuilder; @Bean public TaskletStep masterStep() { return this.masterStepBuilderFactory .get("masterStep") .chunk(100) .reader(itemReader()) .outputChannel(outgoingRequestsToWorkers()) .inputChannel(incomingRepliesFromWorkers()) .build(); } @Bean public IntegrationFlow worker() { return this.workerBuilder .itemProcessor(itemProcessor()) .itemWriter(itemWriter()) .inputChannel(incomingRequestsFromMaster()) .outputChannel(outgoingRepliesToMaster()) .build(); } // Middleware beans setup omitted }
このアノテーションは基盤となるbean設定の負荷を軽減します。ワーカー側のSpring Integration flowと同じように、マスターのstepを設定します。remote chunkingのこれら新規APIを使用するサンプルはsamples moduleで、詳細はSpring Batch Integrationにあります。
remote chunking設定の簡易化に加えて、今回のバージョンはremote partitioningのセットアップを簡易化するAPI、RemotePartitioningMasterStepBuilder
とRemotePartitioningWorkerStepBuilder
、も導入しています。以下例のように@EnableBatchIntegration
を付与することで、これらのbeanをautowiredできます。
@Configuration @EnableBatchProcessing @EnableBatchIntegration public class RemotePartitioningAppConfig { @Autowired private RemotePartitioningMasterStepBuilderFactory masterStepBuilderFactory; @Autowired private RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory; @Bean public Step masterStep() { return this.masterStepBuilderFactory .get("masterStep") .partitioner("workerStep", partitioner()) .gridSize(10) .outputChannel(outgoingRequestsToWorkers()) .inputChannel(incomingRepliesFromWorkers()) .build(); } @Bean public Step workerStep() { return this.workerStepBuilderFactory .get("workerStep") .inputChannel(incomingRequestsFromMaster()) .outputChannel(outgoingRepliesToMaster()) .chunk(100) .reader(itemReader()) .processor(itemProcessor()) .writer(itemWriter()) .build(); } // Middleware beans setup omitted }
この新規APIの詳細はSpring Batch Integrationを参照してください。
1.3. JSON support
Spring Batch 4.1はJSONフォーマットをサポートします。今回リリースは以下フォーマットのJSONを読み込むitem readerを追加しました。
[ { "isin": "123", "quantity": 1, "price": 1.2, "customer": "foo" }, { "isin": "456", "quantity": 2, "price": 1.4, "customer": "bar" } ]
XML用のStaxEventItemReader
の類似機能で、JsonItemReader
はchunkのJSONオブジェクトを読み込むのにストリーミングAPIを使用します。Spring Batchは以下2つのライブラリをサポートします。
上記以外のライブラリを使う場合、JsonObjectReader
インタフェースを実装してください。
また、JSONデータの書き込みにはJsonFileItemWriter
があります。JSONサポートの詳細については、ItemReaders and ItemWritersを参照してください。
1.4. Bean Validation API support
今回リリースではValidatingItemProcessor
実装のBeanValidatingItemProcessor
を提供しており、これはBean Validation API (JSR-303)アノテーションでitemをvalidateします。例えば、以下のPerson
があるとします。
class Person { @NotEmpty private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
BeanValidatingItemProcessor
のbeanを作成してchunk stepにprocessorとしてアプリケーションコンテキストに登録してitemをvalidateします。
@Bean public BeanValidatingItemProcessor<Person> beanValidatingItemProcessor() throws Exception { BeanValidatingItemProcessor<Person> beanValidatingItemProcessor = new BeanValidatingItemProcessor<>(); beanValidatingItemProcessor.setFilter(true); return beanValidatingItemProcessor; }
1.5. JSR-305 support
今回リリースはJSR-305向けの機能を追加しています。Spring FrameworkのNull-safetyアノテーションを使用し、Spring Batchのpublic APIに追加します。
これらアノテーションはSpring Batch API使用時にnull-safetyを強制するだけでなく、IDEにnullに関する有用な情報を提供するのにも使えます。たとえば、ItemReader
インタフェースを実装するとして、JSR-305アノテーションをサポートするIDEは以下を生成可能になります。
public class MyItemReader implements ItemReader<String> { @Nullable public String read() throws Exception { return null; } }
read
メソッドの@Nullable
アノテーションがnull
を返す可能性があるという契約を明示しています。Javadocの記述である、read
メソッドはデータソース読み込み完了時にnull
を返す、をアノテーションにより強制しています。
1.6. FlatFileItemWriterBuilder enhancements
今回リリースの小規模変更にフラットファイル書き込み設定簡易化があります。具体的には、デリミタと固定幅ファイルの簡易化です。以下は変更前と後の例です。
// Before @Bean public FlatFileItemWriter<Item> itemWriter(Resource resource) { BeanWrapperFieldExtractor<Item> fieldExtractor = new BeanWrapperFieldExtractor<Item>(); fieldExtractor.setNames(new String[] {"field1", "field2", "field3"}); fieldExtractor.afterPropertiesSet(); DelimitedLineAggregator aggregator = new DelimitedLineAggregator(); aggregator.setFieldExtractor(fieldExtractor); aggregator.setDelimiter(";"); return new FlatFileItemWriterBuilder<Item>() .name("itemWriter") .resource(resource) .lineAggregator(aggregator) .build(); } // After @Bean public FlatFileItemWriter<Item> itemWriter(Resource resource) { return new FlatFileItemWriterBuilder<Item>() .name("itemWriter") .resource(resource) .delimited() .delimiter(";") .names(new String[] {"field1", "field2", "field3"}) .build(); }