【问题标题】:Spring Batch Stax XML reading job is not ending when out of inputSpring Batch Stax XML读取作业在输入不足时不会结束
【发布时间】:2011-10-15 22:15:19
【问题描述】:

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

我已多次阅读 Batch 文档,但没有看到任何明显的“输入不足时停止作业”配置。

这是我的应用程序上下文的相关部分:

<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 相关的一些重要细微差别,请告诉我。

【问题讨论】:

  • 您可以添加您正在尝试使用的 xml 文件吗?即使是小文件也会发生这种情况吗?您能否为 Spring Batch 启用信息/调试日志记录并发布相关部分。
  • 我不得不离开这个问题几天,然后再回来解决这个问题。我们的 XML 文件非常基本,很像 Spring Batch 文档中的示例,其中 包含多个子 元素。

标签: xml spring jaxb spring-batch stax


【解决方案1】:

我自己解决了这个问题,但我对自己必须做的事情感到惊讶。通过 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

【讨论】:

  • 这个错误在 3 年后的 2014 年底仍然存在!
  • 这很不幸。自从激发了我最初发帖的项目以来,我并没有回到 Spring Batch 领域。
  • 今天刚打这个。我有 Spring Integration 将 Spring Batch 称为独立应用程序。我们调用一个需要很长时间才能返回的外部 URL。
  • 我不再有此代码可用(抱歉,这是 4 年前的事了!)但我在上面描述了我对自定义阅读器的方法。
猜你喜欢
  • 2016-10-03
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 2018-08-31
相关资源
最近更新 更多