Spring -Batch: java.io.ioException: Stream -Ausnahme geschlossen beim Kombinieren von MultireSourceitemwriter und FlatFileItemwriter

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

  •  05-07-2019
  •  | 
  •  

Frage

Ich habe einen Spring -Batch -Prozess, der eine Reihe von Zeilen in der Datenbank enthält und eine Reihe von Flatendateien aus diesen Zeilen und 10 Zeilen pro Datei erstellt. Dazu habe ich einen Frühlings -Batch -Prozess erstellt, der dem ähnlich ist:

<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" />

Das obige Beispiel liest aus einer flachen Datei und gibt eine flache Datei aus (um das Problem anzuzeigen). Beachten Sie das comment-interval = 2 im Chunk und die ItemCountLimitPerResource = 2 im MultireSourceItemwriter.

Der Headerfoterercallback macht Folgendes:

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

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

Ich muss in der Lage sein, genau die Anzahl der Zeilen anzugeben, die in der Datei angezeigt werden.

Für die folgende Eingabedatei:

foo1
foo2
foo3

Ich würde zwei Dateien zur Ausgabe erwarten,


out.1:

file header
foo1
foo2
file footer

out.2:

file header
foo3
file footer

Wenn ich mit Commit-Interval = 2 laufe, bekomme ich eine Ausnahme:

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).

Ich denke, das ist ein Fehler. Die Dateien lauten wie folgt:

out.1:

file header
foo1
foo2

out.2:

file footer

Wenn ich zwei Zeilen in der Eingabedatei habe, funktioniert alles richtig, aber mehr als zwei funktioniert nicht. Wenn ich das Commit-Interval auf 200 ändere, erhalte ich drei Zeilen in einer Datei, was nicht das gewünschte Verhalten ist.

Wenn mir jemand sagen könnte, ob ich etwas falsch mache oder wenn nicht, wie ich das Problem umgehen soll, wäre ich sehr dankbar.

War es hilfreich?

Lösung

In fact, this is a bug. See http://jira.springframework.org/browse/BATCH-1452.

The workaround, according to Dave Syer, is:

The IOException is nasty. A partial workaround is to use the new transactional property in FlatFileItemWriter, setting it to false (BATCH-1449). But then you lose restartability (so if that's not an issue you are good to go). I'll try and fix it properly for 2.1.

Another workaround is to post process the files in a separate step (and not use the header/footer callbacks).

The counting issue (more than 2 items per file) is really separate - the multi-resource writer was never designed to guarantee the precise number of items per file, only to spill over if the limit is breached. You can open a JIRA for an enhancement if you want, A workaround is to use commit-interval="2" in your example (or more generally a factor of the desired file size).

Andere Tipps

Consider, you are trying to read the data from db and writing it to a file. In this scenario, when you are writing the data into file, you need an object to be used at "HeaderFooterCallback" file. how do you do this ?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top