Spring Batch: java.io.IOException: Excepción de flujo cerrado cuando se combina MultiResourceItemWriter y FlatFileItemWriter

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

  •  05-07-2019
  •  | 
  •  

Pregunta

Tengo un proceso de Spring Batch que toma un conjunto de filas en la base de datos y crea una cantidad de archivos planos de esas filas, 10 filas por archivo. Para hacer esto, he creado un proceso Spring Batch, similar a este:

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

El ejemplo anterior se lee desde un archivo plano y sale a un archivo plano (para mostrar el problema). Tenga en cuenta el intervalo de compromiso = 2 en el fragmento y el itemCountLimitPerResource = 2 en el MultiResourceItemWriter.

HeaderFooterCallback hace lo siguiente:

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

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

Necesito poder especificar exactamente el número de líneas que aparecen en el archivo.

Para el siguiente archivo de entrada:

foo1
foo2
foo3

Esperaría dos archivos en la salida,


out.1:

file header
foo1
foo2
file footer

out.2:

file header
foo3
file footer

Cuando ejecuto con commit-interval = 2, obtengo una excepción:

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

Creo que esto es un error. Extrañamente, los archivos son los siguientes:

out.1:

file header
foo1
foo2

out.2:

file footer

Si tengo dos líneas en el archivo de entrada, todo funciona correctamente, pero más de dos no funcionan. Si cambio el intervalo de compromiso a 200, obtengo tres líneas en un archivo, que no es el comportamiento deseado.

Si alguien pudiera decirme si estoy haciendo algo mal, o si no, cómo solucionar el problema, estaría muy agradecido.

¿Fue útil?

Solución

De hecho, esto es un error. Consulte http://jira.springframework.org/browse/BATCH-1452 .

La solución, según Dave Syer , es:

  

La IOException es desagradable. Un parcial   la solución es usar el nuevo   propiedad transaccional en   FlatFileItemWriter, configurándolo en   falso (BATCH-1449). Pero luego pierdes   reiniciabilidad (por lo que si eso no es una   problema, estás listo para ir). Lo intentaré   y arreglarlo correctamente para 2.1.

     

Otra solución es publicar el proceso   los archivos en un paso separado (y no   utilice las devoluciones de llamada del encabezado / pie de página).

     

El problema de contar (más de 2 artículos   por archivo) está realmente separado: el   escritor de múltiples recursos nunca fue   Diseñado para garantizar la precisión.   cantidad de elementos por archivo, solo para   derrame si se rompe el límite.   Puedes abrir un JIRA para una mejora   Si quieres, una solución es usar   intervalo de compromiso = " 2 " en tu ejemplo   (o más generalmente un factor de la   tamaño de archivo deseado).

Otros consejos

Considera que estás intentando leer los datos de db y escribirlos en un archivo. En este escenario, cuando está escribiendo los datos en un archivo, necesita un objeto para ser utilizado en " HeaderFooterCallback " expediente. ¿Cómo haces esto?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top