このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Batch ドキュメント 6.0.6 を使用してください!

既存のサービスと API の再利用

バッチシステムは、他のアプリケーションスタイルと組み合わせて使用されることがよくあります。最も一般的なのはオンラインシステムですが、各アプリケーションスタイルが使用する必要なバルクデータを移動することで、統合やシッククライアントアプリケーションをサポートすることもあります。そのため、多くのユーザーがバッチジョブ内で既存の DAO、サービス、その他の API を再利用したいと考えるのはよくあることです。Spring コンテナー自体は、必要なクラスを注入できるようにすることで、これを比較的容易にします。ただし、既存のサービスまたは API が、別の Spring Batch クラスの依存関係を満たすため、またはステップのメインの ItemReader であるため、ItemReader または ItemWriter として動作する必要がある場合もあります。

既存のサービスの再利用

ラップが必要なサービスごとにアダプタークラスを作成するのは非常に簡単ですが、これはよくある問題であるため、Spring Batch は ItemReaderAdapter と ItemWriterAdapter という実装を提供しています。どちらのクラスも、デリゲートパターンを呼び出すことで標準の Spring メソッドを実装しており、セットアップも非常に簡単です。

  • Java

  • XML

次の Java の例では、ItemReaderAdapter を使用しています。

Java 構成
@Bean
public ItemReaderAdapter itemReader() {
	ItemReaderAdapter reader = new ItemReaderAdapter();

	reader.setTargetObject(fooService());
	reader.setTargetMethod("generateFoo");

	return reader;
}

@Bean
public FooService fooService() {
	return new FooService();
}

次の XML の例では、ItemReaderAdapter を使用しています。

XML 構成
<bean id="itemReader" class="org.springframework.batch.infrastructure.item.adapter.ItemReaderAdapter">
    <property name="targetObject" ref="fooService" />
    <property name="targetMethod" value="generateFoo" />
</bean>

<bean id="fooService" class="org.springframework.batch.infrastructure.item.sample.FooService" />

注意すべき重要な点の 1 つは、targetMethod の契約は read の契約と同じでなければならないということです。使い果たされると、null が返されます。それ以外の場合は、Object を返します。それ以外の場合は、ItemWriter の実装に応じて、フレームワークが処理をいつ終了するかを認識できず、無限ループまたは誤った失敗が発生します。

  • Java

  • XML

次の Java の例では、ItemWriterAdapter を使用しています。

Java 構成
@Bean
public ItemWriterAdapter itemWriter() {
	ItemWriterAdapter writer = new ItemWriterAdapter();

	writer.setTargetObject(fooService());
	writer.setTargetMethod("processFoo");

	return writer;
}

@Bean
public FooService fooService() {
	return new FooService();
}

次の XML の例では、ItemWriterAdapter を使用しています。

XML 構成
<bean id="itemWriter" class="org.springframework.batch.infrastructure.item.adapter.ItemWriterAdapter">
    <property name="targetObject" ref="fooService" />
    <property name="targetMethod" value="processFoo" />
</bean>

<bean id="fooService" class="org.springframework.batch.infrastructure.item.sample.FooService" />

既存 API の再利用

サービス以外にも、Java Iterator (または Iterable)を介してデータを公開する既存の API を、専用の ItemReader を作成することなく再利用したいというニーズもよくあります。Spring Batch はまさにこの目的のために IteratorItemReader を提供します。IteratorItemReader は、任意の Iterator または Iterable を ItemReader 契約に適合させます。

良い例として、Spring Data Commons 3.1 で導入されたスクロール機能が挙げられます。これは、オフセットベースまたはキーセットベースのスクロールを使用して、リポジトリから返される連続する Window インスタンスを反復処理するための WindowIterator を公開します。

  • Java

  • XML

以下の Java の例は、専用のリーダー実装を必要とせずに、Spring Data リポジトリから取得した WindowIterator を ItemReader として再利用する方法を示しています。

Java 構成
interface UserRepository extends Repository<User, Long> {

	Window<User> findFirst10ByLastnameOrderByFirstname(String lastname, KeysetScrollPosition position);

}

@Bean
public ItemReader<User> itemReader(UserRepository userRepository) {
	WindowIterator<User> users = WindowIterator
		.of(position -> userRepository.findFirst10ByLastnameOrderByFirstname("Doe", position))
		.startingAt(ScrollPosition.keyset());

	return new IteratorItemReader<>(users);
}

WindowIterator の構築にはラムダ式が必要なため、<bean> 定義として直接表現することはできません。代わりに、構築ロジックをファクトリメソッドに抽出し、XML から参照することができます。以下にその例を示します。

ファクトリクラス
public class UserItemReaderFactory {

	public static ItemReader<User> createItemReader(UserRepository userRepository) {
		WindowIterator<User> users = WindowIterator
			.of(position -> userRepository.findFirst10ByLastnameOrderByFirstname("Doe", position))
			.startingAt(ScrollPosition.keyset());

		return new IteratorItemReader<>(users);
	}

}
XML 構成
<bean id="itemReader" class="org.springframework.batch.infrastructure.item.sample.UserItemReaderFactory"
      factory-method="createItemReader">
    <constructor-arg ref="userRepository" />
</bean>

このパターンは Spring Data のスクロール API に特有のものではありません。Iterator または Iterable を公開する API であれば、同様の方法で ItemReader にも適用できます。