diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FileWriterCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FileWriterCallback.java new file mode 100644 index 000000000..75a657fd2 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FileWriterCallback.java @@ -0,0 +1,19 @@ +package org.springframework.batch.item.file; + +import java.io.Writer; +import java.io.IOException; + +/** + * Callback interface for writing to a file - useful e.g. for handling headers + * and footers. + * + * @author Robert Kasanicky + */ +public interface FileWriterCallback { + + /** + * Write contents to a file using the supplied {@link Writer}. It is not + * required to flush the writer inside this method. + */ + void write(Writer writer) throws IOException; +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java index ce8fbda86..d74b7da7b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java @@ -23,8 +23,6 @@ import java.io.Writer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.charset.UnsupportedCharsetException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.springframework.batch.item.ExecutionContext; @@ -78,9 +76,9 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement private String encoding = OutputState.DEFAULT_CHARSET; - private List headerLines = new ArrayList(); + private FileWriterCallback headerCallback; - private List footerLines = new ArrayList(); + private FileWriterCallback footerCallback; private String lineSeparator = DEFAULT_LINE_SEPARATOR; @@ -152,24 +150,19 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement } /** - * Public setter for the header lines. These will be output at the head of - * the file before any calls to {@link #write(List)} (and not on restart - * unless the restart is after a failure before the first flush). - * - * @param headerLines the header lines to set + * headerCallback will be called before writing the first item to file. + * Newline will be automatically appended after the header is written. */ - public void setHeaderLines(String[] headerLines) { - this.headerLines = Arrays.asList(headerLines); + public void setHeaderCallback(FileWriterCallback headerCallback) { + this.headerCallback = headerCallback; } /** - * Public setter for footer lines. These will be output at the end of the - * file when the writer is closed. - * - * @param footerLines the footer lines to set + * footerCallback will be called after writing the last item to file, but + * before the file is closed. */ - public void setFooterLines(String[] footerLines) { - this.footerLines = Arrays.asList(footerLines); + public void setFooterCallback(FileWriterCallback footerCallback) { + this.footerCallback = footerCallback; } /** @@ -210,8 +203,9 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement public void close(ExecutionContext executionContext) { if (state != null) { try { - for (String line : footerLines) { - state.write(line + lineSeparator); + if (footerCallback != null) { + footerCallback.write(state.outputBufferedWriter); + state.outputBufferedWriter.flush(); } } catch (IOException e) { @@ -251,13 +245,14 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement throw new ItemStreamException("Failed to initialize writer", ioe); } if (outputState.lastMarkedByteOffsetPosition == 0) { - try { - for (String line : headerLines) { - outputState.write(line + lineSeparator); + if (headerCallback != null) { + try { + headerCallback.write(state.outputBufferedWriter); + state.write("\n"); + } + catch (IOException e) { + throw new FlushFailedException("Could not write headers. The file may be corrupt.", e); } - } - catch (IOException e) { - throw new FlushFailedException("Could not write headers. The file may be corrupt.", e); } } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java index 918c17885..9f2c47fcb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java @@ -25,6 +25,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.Writer; import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; import java.util.Collections; @@ -203,7 +204,13 @@ public class FlatFileItemWriterTests { @Test public void testRestart() throws Exception { - writer.setFooterLines(new String[] { "footer" }); + writer.setFooterCallback(new FileWriterCallback() { + + public void write(Writer writer) throws IOException { + writer.write("footer"); + } + + }); writer.open(executionContext); // write some lines @@ -309,7 +316,13 @@ public class FlatFileItemWriterTests { @Test public void testWriteFooter() throws Exception { - writer.setFooterLines(new String[] { "a", "b" }); + writer.setFooterCallback(new FileWriterCallback() { + + public void write(Writer writer) throws IOException { + writer.write("a\nb"); + } + + }); writer.open(executionContext); writer.write(Collections.singletonList(TEST_STRING)); writer.close(executionContext); @@ -320,7 +333,13 @@ public class FlatFileItemWriterTests { @Test public void testWriteHeader() throws Exception { - writer.setHeaderLines(new String[] { "a", "b" }); + writer.setHeaderCallback(new FileWriterCallback() { + + public void write(Writer writer) throws IOException { + writer.write("a\nb"); + } + + }); writer.open(executionContext); writer.write(Collections.singletonList(TEST_STRING)); writer.close(null); @@ -334,7 +353,13 @@ public class FlatFileItemWriterTests { @Test public void testWriteHeaderAfterRestartOnFirstChunk() throws Exception { - writer.setHeaderLines(new String[] { "a", "b" }); + writer.setHeaderCallback(new FileWriterCallback() { + + public void write(Writer writer) throws IOException { + writer.write("a\nb"); + } + + }); writer.open(executionContext); writer.write(Collections.singletonList(TEST_STRING)); writer.close(executionContext); @@ -353,7 +378,13 @@ public class FlatFileItemWriterTests { @Test public void testWriteHeaderAfterRestartOnSecondChunk() throws Exception { - writer.setHeaderLines(new String[] { "a", "b" }); + writer.setHeaderCallback(new FileWriterCallback() { + + public void write(Writer writer) throws IOException { + writer.write("a\nb"); + } + + }); writer.open(executionContext); writer.write(Collections.singletonList(TEST_STRING)); writer.update(executionContext);