退出输入时,Spring Batch Stax XML读取作业不会结束

时间:2011-10-15 22:15:19

标签: xml spring jaxb spring-batch stax

我正在使用Spring Batch来设置一个处理可能非常大的XML文件的作业。我认为我已经适当地设置了它,但是在运行时我发现作业运行,处理它的输入,然后只是挂起一个执行状态(我可以通过查看JobRepository在JobRepository中的状态来确认)。 p>

我已经多次阅读批处理文档,但是我没有看到任何明显的“在输入时使作业停止”配置,我缺少。

以下是我的申请背景的相关部分:

<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”只是一个记录将要写入的项目的类。

如果我错过了与Batch和/或Stax有关的一些重要细微差别,请告诉我。

1 个答案:

答案 0 :(得分: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滚动我自己的ItemReader,但根本没有使用FragmentEventReader,然后将内部循环代码调整为如下所示:

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

完美无缺,并允许我的批处理作业在输入结束时进入COMPLETED。

但是,我真的很惊讶我必须这样做。我想知道我使用的流式XML库的底层实现是否有问题,但我使用的是Spring Batch依赖列表中引用的stax2-api-3.0.1.jar。

我还发现我是not alone