Spring批处理:java.io.IOException:组合MultiResourceItemWriter和FlatFileItemWriter时出现流关闭异常

Spring批处理:java.io.IOException:组合MultiResourceItemWriter和FlatFileItemWriter时出现流关闭异常,java,spring,spring-batch,Java,Spring,Spring Batch,我有一个Spring批处理过程,它获取数据库中的一组行,并从这些行创建许多平面文件,每个文件10行。为此,我创建了一个Spring批处理过程,类似于: <batch:job id="springTest" job-repository="jobRepository" restartable="true"> <batch:step id="test"> <batch:tasklet> <batch:chunk

我有一个Spring批处理过程,它获取数据库中的一组行,并从这些行创建许多平面文件,每个文件10行。为此,我创建了一个Spring批处理过程,类似于:

<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" />
我需要能够准确地指定文件中出现的行数

对于以下输入文件:

foo1
foo2
foo3
我希望输出两个文件


第1条:

file header
foo1
foo2
file footer
file header
foo1
foo2
第2条:

file header
foo3
file footer
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).
我认为这是一个错误。具体来说,文件如下:

第1条:

file header
foo1
foo2
file footer
file header
foo1
foo2
第2条:

file header
foo3
file footer
file footer
如果输入文件中有两行,则所有内容都可以正常工作,但超过两行则无法正常工作。如果我将提交间隔更改为200,那么一个文件中会有三行,这不是所需的行为


如果有人能告诉我我是否做错了什么,或者如果没有告诉我如何避开这个问题,我将非常感激。

事实上,这是一个bug。看

根据,解决办法是:

这个例外很糟糕。局部 解决方法是使用新的 中的事务属性 FlatFileItemWriter,将其设置为 假(批号:1449)。但是你输了 可重启性(如果不是 问题:你可以走了)。我试试看 并将其正确地固定在2.1中

另一个解决方法是后处理 在单独的步骤中删除文件(而不是 使用页眉/页脚回调)

盘点问题(超过2项) 每个文件)是真正独立的 多资源编写器从未被使用过 旨在确保精确的 每个文件的项目数,仅限于 如果超出限制,则溢出。 您可以打开JIRA进行增强 如果您愿意,可以使用 在您的示例中,commit interval=“2” (或更一般地说,是 所需的文件大小)


事实上,这是一个bug。看

根据,解决办法是:

这个例外很糟糕。局部 解决方法是使用新的 中的事务属性 FlatFileItemWriter,将其设置为 假(批号:1449)。但是你输了 可重启性(如果不是 问题:你可以走了)。我试试看 并将其正确地固定在2.1中

另一个解决方法是后处理 在单独的步骤中删除文件(而不是 使用页眉/页脚回调)

盘点问题(超过2项) 每个文件)是真正独立的 多资源编写器从未被使用过 旨在确保精确的 每个文件的项目数,仅限于 如果超出限制,则溢出。 您可以打开JIRA进行增强 如果您愿意,可以使用 在您的示例中,commit interval=“2” (或更一般地说,是 所需的文件大小)


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

考虑一下,您正在尝试从数据库中读取数据并将其写入文件。在这种情况下,将数据写入文件时,需要在“HeaderFooterCallback”文件中使用一个对象。如何做到这一点?

我将事务属性设置为false,但仍然有一个异常,流关闭,在关闭前写入页脚失败。那么解决办法是什么呢?为什么当我将事务设置为false时,还没有解决问题?提前感谢,我将transactional属性设置为false,但仍然有一个异常,Stream closed,未能在关闭前写入页脚。那么解决办法是什么呢?为什么当我将事务设置为false时,还没有解决问题?提前谢谢