【问题标题】:Spring Batch: java.io.IOException: Stream closed exception when combining MultiResourceItemWriter and FlatFileItemWriterSpring Batch:java.io.IOException:组合 MultiResourceItemWriter 和 FlatFileItemWriter 时流关闭异常
【发布时间】:2009-11-26 14:39:55
【问题描述】:

我有一个 Spring Batch 进程,它在数据库中获取一组行,并从这些行创建多个平面文件,每个文件 10 行。为此,我创建了一个 Spring Batch 流程,类似于:

<batch:job id="springTest" job-repository="jobRepository" restartable="true">
    <batch:step id="test">
        <batch:tasklet>
            <batch:chunk reader="itemReader" writer="multipleItemWriter" commit-interval="2" />
        </batch:tasklet>
    </batch:step>
</batch:job>

<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
    <property name="resource" value="file:/temp/temp-input.txt" />
    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.PassThroughLineMapper" />
    </property>
</bean>

<bean id="multipleItemWriter" class="org.springframework.batch.item.file.MultiResourceItemWriter">
    <property name="resource" value="file:/temp/temp-out" />
    <property name="itemCountLimitPerResource" value="2" />
    <property name="delegate">
        <bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
            <property name="lineAggregator">
              <bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
            </property>
            <property name="encoding" value="utf-8" />
            <property name="headerCallback" ref="headerFooter" />
            <property name="footerCallback" ref="headerFooter" />
        </bean>
   </property>
</bean>

<bean id="headerFooter" class="uk.co.farwell.spring.HeaderFooterCallback" />

上面的示例从一个平面文件中读取并输出到一个平面文件(以显示问题)。注意块中的 commit-interval=2,以及 MultiResourceItemWriter 中的 itemCountLimitPerResource=2。

HeaderFooterCallback 执行以下操作:

public void writeHeader(Writer writer) throws IOException {
    writer.write("file header\n");
}

public void writeFooter(Writer writer) throws IOException {
    writer.write("file footer\n");
}

我需要能够准确指定文件中出现的行数。

对于以下输入文件:

foo1
foo2
foo3

我希望输出两个文件,


out.1:

file header
foo1
foo2
file footer

out.2:

file header
foo3
file footer

当我以 commit-interval=2 运行时,我得到一个异常:

2009-11-26 15:32:46,734 ERROR .support.TransactionSynchronizationUtils - TransactionSynchronization.afterCompletion threw exception
org.springframework.batch.support.transaction.FlushFailedException: Could not write to output buffer
    at org.springframework.batch.support.transaction.TransactionAwareBufferedWriter$1.afterCompletion(TransactionAwareBufferedWriter.java:71)
    at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCompletion(TransactionSynchronizationUtils.java:157)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:974)
    .
    .
    .
Caused by: java.io.IOException: Stream closed
    at sun.nio.cs.StreamEncoder.ensureOpen(Unknown Source)
    at sun.nio.cs.StreamEncoder.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.write(Unknown Source)
    at java.io.Writer.write(Unknown Source)
    at org.springframework.batch.support.transaction.TransactionAwareBufferedWriter$1.afterCompletion(TransactionAwareBufferedWriter.java:67).

我认为这是一个错误。奇怪的是,文件如下:

out.1:

file header
foo1
foo2

out.2:

file footer

如果输入文件中有两行,则一切正常,但多于两行则无法正常工作。如果我将提交间隔更改为 200,那么我会在一个文件中得到三行,这不是想要的行为。

如果有人能告诉我我做错了什么,或者如果不是如何解决问题,我将不胜感激。

【问题讨论】:

    标签: java spring spring-batch


    【解决方案1】:

    事实上,这是一个错误。见http://jira.springframework.org/browse/BATCH-1452

    根据Dave Syer,解决方法是:

    IOException 很讨厌。一个部分 解决方法是使用新的 交易性财产 FlatFileItemWriter,将其设置为 错误 (BATCH-1449)。但后来你输了 可重启性(所以如果那不是 问题你很好去)。我会尽力 并为 2.1 正确修复它。

    另一种解决方法是发布流程 文件在一个单独的步骤中(而不是 使用页眉/页脚回调)。

    计数问题(超过 2 个项目 每个文件)真的是分开的 - 多资源作家从来没有 旨在保证精确 每个文件的项目数,仅 如果超出限制溢出。 您可以打开 JIRA 进行增强 如果需要,一种解决方法是使用 commit-interval="2" 在您的示例中 (或更一般地,一个因素 所需的文件大小)。

    【讨论】:

    • 我将事务属性设置为false,但我仍然有这个异常,流关闭,关闭前无法写入页脚。那么解决方案是什么?为什么当我将事务设置为 false 时,还没有解决问题?提前致谢
    【解决方案2】:

    考虑一下,您正在尝试从 db 读取数据并将其写入文件。在这种情况下,当您将数据写入文件时,您需要在“HeaderFooterCallback”文件中使用一个对象。你是怎么做到的?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2014-05-18
      • 1970-01-01
      相关资源
      最近更新 更多