Весенняя партия:java.io.IOException Исключение:Исключение закрытия потока при объединении MultiResourceItemWriter и FlatFileItemWriter
-
05-07-2019 - |
Вопрос
У меня есть пакетный процесс Spring, который берет набор строк в базе данных и создает несколько плоских файлов из этих строк, по 10 строк на файл.Чтобы сделать это, я создал весенний пакетный процесс, подобный этому:
<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" />
Приведенный выше пример считывает данные из плоского файла и выводит в плоский файл (чтобы показать проблему).Обратите внимание на интервал фиксации =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
Я бы ожидал, что на выходе будет два файла,
вон.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).
Я думаю, что это ошибка.Как ни странно, файлы выглядят следующим образом:
вон.1:
file header
foo1
foo2
выход.2:
file footer
Если у меня есть две строки во входном файле, все работает правильно, но больше двух не работает.Если я изменю интервал фиксации на 200, то я получу три строки в одном файле, что не соответствует желаемому поведению.
Если бы кто-нибудь мог сказать мне, делаю ли я что-то неправильно, или если нет, то как обойти проблему, я был бы очень благодарен.
Решение
На самом деле, это ошибка.Видишь http://jira.springframework.org/browse/BATCH-1452.
Обходной путь, согласно Дэйв Сайер, является:
Исключение IOException является неприятным.Частичный обходной путь заключается в использовании нового транзакционного свойства в FlatFileItemWriter, установив для него значение false (BATCH-1449).Но тогда вы теряете возможность перезапуска (так что, если это не проблема , все в порядке).Я попробую и исправлю это должным образом для версии 2.1.
Другим обходным путем является обработка post файлов на отдельном шаге (а не использование обратных вызовов верхнего / нижнего колонтитулов).
Проблема с подсчетом (более 2 элементов на файл) действительно отдельная - средство записи с несколькими ресурсами никогда не было разработано так, чтобы гарантировать точное количество элементов в файле, только для того, чтобы перетекать, если лимит нарушен.Вы можете открыть JIRA для улучшения если вы хотите, обходным путем является использование в вашем примере commit-interval="2" (или, в более общем смысле, коэффициент желаемого размера файла).
Другие советы
Представьте, что вы пытаетесь считывать данные из базы данных и записывать их в файл.В этом сценарии, когда вы записываете данные в файл, вам нужен объект, который будет использоваться в файле "HeaderFooterCallback".как ты это делаешь ?