16

私は春のバッチジョブを書いていますが、私のステップの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上記のコードは機能しますが、 1つ以上のコードを使用できるエッジ ケースがいくつかあることがわかりましたNewsletterSubscriberAccountそのため、状態チェックを削除して、アイテム ライターに複数渡す必要があります。

私が見つけた1つの解決策は、両方を変更し、ItemProcessor代わりにタイプItemWriterを処理することですが、これには2つの欠点があります。List<Account>Account

  • ライターのネストされたリストのために、コードとテストはより醜く、作成と保守が困難です
  • 最も重要なのは、複数のAccountオブジェクトが同じトランザクションで書き込まれる可能性があることです。ライターに指定されたリストには複数のアカウントが含まれる可能性があり、これを避けたいからです。

おそらくリスナーを使用するか、スプリングバッチで使用される内部コンポーネントを置き換えて、プロセッサのリストを回避する方法はありますか?

アップデート

この問題について、 Spring Jira でイシューをオープンしました。

拡張ポイントとしてマークされているisCompleteおよびgetAdjustedOutputsメソッドを調べて、目標を達成するために何らかの方法でそれらを使用できるかどうかを確認しています。FaultTolerantChunkProcessorSimpleChunkProcessor

どんなヒントでも大歓迎です。

4

4 に答える 4

16

Item Processor は 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);
        }
    }
}
于 2016-02-26T05:08:01.853 に答える
5

ItemProcessor雑草にかなり深く入ることなく、Spring Batchへの呼び出しごとに複数のアイテムを返す方法はありません。ItemProcessoranとItemWriterexitの関係がどこにあるかを本当に知りたい場合(推奨されません)、ChunkProcessorインターフェースの実装を見てください。単純なケース ( SimpleChunkProcessor) はそれほど悪くありませんが、フォールト トレラント ロジック ( を介してスキップ/再試行FaultTolerantChunkProcessor) を使用すると、非常に扱いにくいほど高速になります。

はるかに簡単なオプションはItemReader、アイテムを返す前に、このロジックをこのエンリッチメントを行う に移動することです。アイテムを返す前にサービス ルックアップを実行ItemReaderするカスタム実装で使用しているものをすべてラップします。ItemReaderこの場合、NewsletterSubscriberリーダーからa を返す代わりAccountに、前の情報に基づいて a を返します。

于 2014-06-03T00:13:22.060 に答える