私はSpringBatchジョブを書いていますが、私のステップの1つに、プロセッサ用の次のコードがあります。
@Component
public class SubscriberProcessor implements ItemProcessor<NewsletterSubscriber, Account>, InitializingBean {
@Autowired
private AccountService service;
@Override public Account process(NewsletterSubscriber item) throws Exception {
if (!Strings.isNullOrEmpty(item.getId())) {
return service.getAccount(item.getId());
}
// search with email address
List<Account> accounts = service.findByEmail(item.getEmail());
checkState(accounts.size() <= 1, "Found more than one account with email %s", item.getEmail());
return accounts.isEmpty() ? null : accounts.get(0);
}
@Override public void afterPropertiesSet() throws Exception {
Assert.notNull(service, "account service must be set");
}
}
上記のコードは機能しますが、Account
ごとに複数のNewsletterSubscriber
を持つことが許可されるEdgeのケースがいくつかあることがわかりました。したがって、状態チェックを削除し、複数のAccount
をアイテムライターに渡す必要があります。
私が見つけた解決策の1つは、ItemProcessor
とItemWriter
の両方を変更してAccount
ではなくList<Account>
タイプを処理することですが、これには2つの欠点があります。
Account
オブジェクトが書き込まれる可能性があるためです。これは避けたいと思います。リスナーを使用する方法や、プロセッサのリストを回避するためにSpring Batchで使用される内部コンポーネントを置き換える方法はありますか?
この問題のために 春のJiraの問題 を開きました。
isComplete および getAdjustedOutputsFaultTolerantChunkProcessor
のメソッドを調べています。これらは、 SimpleChunkProcessor
で拡張ポイントとしてマークされています。目標を達成するために何らかの方法でそれらを使用できるかどうかを確認します。
ヒントは大歓迎です。
アイテムプロセッサは1つのものを取り込んで、リストを返します
MyItemProcessor implements ItemProcessor<SingleThing,List<ExtractedThingFromSingleThing>> {
public List<ExtractedThingFromSingleThing> process(SingleThing thing) {
//parse and convert to list
}
}
ダウンストリームライターをラップして問題を解決します。このようにすると、このライターのダウンストリームのものはリストを操作する必要がありません。
@StepScope
public class ItemListWriter<T> implements ItemWriter<List<T>> {
private ItemWriter<T> wrapped;
public ItemListWriter(ItemWriter<T> wrapped) {
this.wrapped = wrapped;
}
@Override
public void write(List<? extends List<T>> items) throws Exception {
for (List<T> subList : items) {
wrapped.write(subList);
}
}
}
雑草にかなり深く入り込むことなく、SpringBatchのItemProcessor
への呼び出しごとに複数のアイテムを返す方法はありません。 ItemProcessor
とItemWriter
の関係がどこにあるのかを本当に知りたい場合は(非推奨)、ChunkProcessor
インターフェースの実装を見てください。単純なケース(SimpleChunkProcessor
)はそれほど悪くはありませんが、フォールトトレラントロジック(FaultTolerantChunkProcessor
を介したスキップ/再試行)のいずれかを使用すると、非常に手に負えないほど速くなります。
はるかに簡単なオプションは、このロジックをItemReader
に移動して、アイテムを返す前にこのエンリッチメントを実行することです。アイテムを返す前にサービスルックアップを実行するカスタムItemReader
実装で使用しているItemReader
をラップします。この場合、リーダーからNewsletterSubscriber
を返す代わりに、前の情報に基づいてAccount
を返します。
アカウントを返す代わりに、AccountWrapperまたはCollectionを作成します。ライターは明らかにこれを考慮に入れる必要があります:)