스프링 배치 : java.io.ioexception : multiresourceitemwriter와 flatfileitemwriter를 결합 할 때 스트림 폐쇄 예외

StackOverflow https://stackoverflow.com/questions/1804042

  •  05-07-2019
  •  | 
  •  

문제

데이터베이스에서 행 세트를 가져 오는 스프링 배치 프로세스가 있으며 해당 행에서 여러 플랫 파일을 파일 당 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" />

위의 예제는 플랫 파일에서 읽고 플랫 파일로 출력됩니다 (문제를 보여주기 위해). 청크에서 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

입력 파일에 두 줄이 있으면 모든 것이 올바르게 작동하지만 둘 이상이 작동하지 않습니다. Commit-InterVal을 200으로 변경하면 하나의 파일로 3 줄이 발생합니다. 이는 원하는 동작이 아닙니다.

누군가 내가 뭔가 잘못하고 있는지 말해 줄 수 있거나 문제를 해결하는 방법이 없다면 매우 감사 할 것입니다.

도움이 되었습니까?

해결책

사실, 이것은 버그입니다. 보다 http://jira.springframework.org/browse/batch-1452.

에 따르면 해결 방법 Dave Syer, 이다:

ioexception은 불쾌합니다. 부분 해결 방법은 flatfileitemwriter의 새로운 트랜잭션 속성을 사용하여 False (Batch-1449)로 설정하는 것입니다. 그러나 재시작 가능성을 잃습니다 (따라서 문제가되지 않으면 좋은 문제). 나는 2.1에 대해 올바르게 고칠 것이다.

또 다른 해결 방법은 파일을 별도의 단계로 처리하는 것입니다 (헤더/바닥 글 콜백을 사용하지 않음).

카운팅 문제 (파일 당 2 개 이상의 항목)는 실제로 분리되어 있습니다. 멀티 자원 작가는 파일 당 정확한 수의 항목을 보장하도록 설계되지 않았으며 한도를 위반 한 경우에만 유출됩니다. 원하는 경우 향상을 위해 JIRA를 열 수 있습니다. 해결 방법은 예제에서 Commit-InterVal = "2"를 사용하는 것입니다 (또는 더 일반적으로 원하는 파일 크기의 요소).

다른 팁

DB의 데이터를 읽고 파일에 작성하려고합니다. 이 시나리오에서는 데이터를 파일에 작성할 때 "HeaderfooterCallback"파일에서 객체를 사용해야합니다. 이 작업을 어떻게합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top