2

Spring Batchを使用して、非常に大きなXMLファイルを処理する可能性のあるジョブを設定しています。適切に設定したと思いますが、実行時にジョブが実行され、入力が処理され、実行状態でハングすることがわかりました(JobRepositoryでJobExecutionのステータスを確認することで確認できます)。

バッチのドキュメントを数回読みましたが、欠落している明らかな「入力がなくなったときにジョブを停止する」構成が表示されません。

これが私のアプリケーションコンテキストの関連部分です:

<batch:job id="processPartnerUploads" restartable="true">
    <batch:step id="processStuffHoldings">
        <batch:tasklet>
            <batch:chunk reader="stuffReader" writer="stuffWriter" commit-interval="1"/>
        </batch:tasklet>        
    </batch:step>
</batch:job>

<bean id="stuffReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
  <property name="fragmentRootElementName" value="stuff" />
  <property name="resource" value="file:///path/to/file.xml" />
  <property name="unmarshaller" ref="stuffUnmarshaller" />
</bean>

<bean id="stuffUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="contextPath" value="com.company.project.xmlcontext"/>
</bean>

<bean id="stuffWriter" class="com.company.project.batch.StuffWriter" />

重要な場合、「StuffWriter」は、書き込まれるアイテムをログに記録する単なるクラスです。

バッチやスタックスに関連する重要なニュアンスを見逃した場合はお知らせください。

4

1 に答える 1

2

私は自分でこの問題を解決しましたが、私がしなければならなかったことに驚いています。StaxEventItemReaderを介してデバッグすると、ドキュメントの最後に到達すると、moveCursorToNextFragment()メソッドの内部ループが無限大になることに気付きました。関連するコードは次のとおりです。

while (true) {
    while (reader.peek() != null && !reader.peek().isStartElement()) {
        reader.nextEvent();
    }
    if (reader.peek() == null) {
        return false;
    }
    QName startElementName = ((StartElement) reader.peek()).getName();
    if (startElementName.getLocalPart().equals(fragmentRootElementName)) {
        if (fragmentRootElementNameSpace == null
    || startElementName.getNamespaceURI().equals(fragmentRootElementNameSpace)) {
           return true;
        }
     }
    reader.nextEvent();
 }

reader.peek()がnullを返すことはありませんでした。このコードは、peek()中に発生したXMLEventがドキュメントの最後にあるかどうかを確認する必要があるように見えましたが、StaxEventItemReaderが標準のXMLEventReaderをラップするDefaultFragmentEventReaderに依存しているため、これはそれほど単純ではありませんでした。

私がやったことは、StaxEventItemReaderに基づいてFragmentEventReaderをまったく使用せずに、独自のItemReaderをローリングし、内部ループコードを次のように調整することでした。

        if (reader.peek().getEventType() == XMLStreamConstants.END_DOCUMENT) {
            return false;
        }
        reader.nextEvent();

これは完全に機能し、入力の最後にバッチジョブをCOMPLETEDにすることができます。

しかし、私はこれをしなければならなかったことに本当に驚いています。使用していたストリーミングXMLライブラリの基盤となる実装に問題があるのではないかと思いましたが、SpringBatchの依存関係リストで参照されているstax2-api-3.0.1.jarを使用しています。

また、私は一人ではないことがわかりました。

于 2011-10-18T20:21:09.790 に答える