Spring Batch: java.io.IOException: поток закрытое исключение при объединении MultiResourceItemWriter и FlatFileItemWriter - PullRequest
1 голос
/ 26 ноября 2009

У меня есть процесс 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 в чанке и itemCountLimitPerResource = 2 в MultiResourceItemWriter.

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

Вых.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

Вых.2:

file footer

Если у меня есть две строки во входном файле, все работает правильно, но более двух не работает. Если я изменю интервал фиксации на 200, то получу три строки в одном файле, что не соответствует требуемому поведению.

Если бы кто-то мог сказать мне, если я делаю что-то не так, или если нет, как обойти проблему, я был бы очень благодарен.

Ответы [ 2 ]

3 голосов
/ 27 ноября 2009

На самом деле это ошибка. Смотри http://jira.springframework.org/browse/BATCH-1452.

Обходной путь, согласно Дейву Сайеру , составляет:

IOException является мерзким. Частичное Обходной путь должен использовать новый транзакционная собственность в FlatFileItemWriter, установив его в ложь (BATCH-1449). Но тогда ты проиграл перезапускаемость (так что если это не вопрос вы готовы идти). я буду стараться и исправить это правильно для 2.1.

Еще один обходной путь - постобработка файлы в отдельном шаге (а не используйте обратные вызовы верхнего / нижнего колонтитула).

Вопрос подсчета (более 2 предметов) на файл) действительно отдельно - многоресурсный писатель никогда не был разработан, чтобы гарантировать точный количество элементов в файле, только разлив, если предел нарушен. Вы можете открыть JIRA для улучшения Если вы хотите, Обходной путь должен использовать commit-interval = "2" в вашем примере (или, в более общем случае, фактор желаемый размер файла).

1 голос
/ 22 сентября 2011

Учтите, что вы пытаетесь прочитать данные из БД и записать их в файл. В этом случае, когда вы записываете данные в файл, вам нужен объект, который будет использоваться в файле «HeaderFooterCallback». как ты это делаешь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...