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 6748a03b4..62fd65f5e 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 @@ -469,7 +469,14 @@ InitializingBean { */ public void restoreFrom(ExecutionContext executionContext) { lastMarkedByteOffsetPosition = executionContext.getLong(getExecutionContextKey(RESTART_DATA_NAME)); - restarted = true; + linesWritten = executionContext.getLong(getExecutionContextKey(WRITTEN_STATISTICS_NAME)); + if (shouldDeleteIfEmpty && linesWritten == 0) { + // previous execution deleted the output file because no items were written + restarted = false; + lastMarkedByteOffsetPosition = 0; + } else { + restarted = true; + } } /** @@ -585,7 +592,6 @@ InitializingBean { } initialized = true; - linesWritten = 0; } public boolean isInitialized() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java index fd3bb5c1c..c81c36250 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java @@ -368,6 +368,13 @@ ResourceAwareItemWriterItemStream, InitializingBean { startAtPosition = executionContext.getLong(getExecutionContextKey(RESTART_DATA_NAME)); currentRecordCount = executionContext.getLong(getExecutionContextKey(WRITE_STATISTICS_NAME)); restarted = true; + if (shouldDeleteIfEmpty && currentRecordCount == 0) { + // previous execution deleted the output file because no items were written + restarted = false; + startAtPosition = 0; + } else { + restarted = true; + } } open(startAtPosition, restarted); 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 e75d55bd5..22d125aba 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 @@ -323,8 +323,8 @@ public class FlatFileItemWriterTests { assertEquals("footer", readLine()); - // 3 lines were written to the file after restart - assertEquals(3, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); + // 8 lines were written to the file in total + assertEquals(8, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); } @@ -425,8 +425,8 @@ public class FlatFileItemWriterTests { assertEquals("footer", readLine()); - // 3 lines were written to the file after restart - assertEquals(3, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); + // 8 lines were written to the file in total + assertEquals(8, executionContext.getLong(ClassUtils.getShortName(FlatFileItemWriter.class) + ".written")); } @@ -595,6 +595,7 @@ public class FlatFileItemWriterTests { public void testDeleteOnExitReopen() throws Exception { writer.setShouldDeleteIfEmpty(true); writer.open(executionContext); + writer.update(executionContext); assertTrue(outputFile.exists()); writer.close(); assertFalse(outputFile.exists()); @@ -603,6 +604,30 @@ public class FlatFileItemWriterTests { assertEquals("test2", readLine()); } + @Test + public void testWriteHeaderAndDeleteOnExitReopen() throws Exception { + writer.setHeaderCallback(new FlatFileHeaderCallback() { + + @Override + public void writeHeader(Writer writer) throws IOException { + writer.write("a\nb"); + } + + }); + writer.setShouldDeleteIfEmpty(true); + writer.open(executionContext); + writer.update(executionContext); + assertTrue(outputFile.exists()); + writer.close(); + assertFalse(outputFile.exists()); + + writer.open(executionContext); + writer.write(Collections.singletonList("test2")); + assertEquals("a", readLine()); + assertEquals("b", readLine()); + assertEquals("test2", readLine()); + } + @Test public void testDeleteOnExitNoRecordsWrittenAfterRestart() throws Exception { writer.setShouldDeleteIfEmpty(true); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java index 2901b5deb..7515d2f2e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java @@ -443,7 +443,7 @@ public class StaxEventItemWriterTests { * Test that the writer can restart if the previous execution deleted empty file. */ @Test - public void testDeleteIfEmptyRestart() throws Exception { + public void testDeleteIfEmptyRestartAfterDelete() throws Exception { writer.setShouldDeleteIfEmpty(true); writer.open(executionContext); writer.update(executionContext); @@ -452,11 +452,63 @@ public class StaxEventItemWriterTests { writer = createItemWriter(); writer.setShouldDeleteIfEmpty(true); writer.open(executionContext); + writer.write(items); + writer.update(executionContext); writer.close(); String content = getOutputFileContent(); assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); } + /** + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set (restart after delete). + */ + @Test + public void testDeleteIfEmptyNoRecordsWrittenHeaderAndFooterRestartAfterDelete() throws Exception { + writer.setShouldDeleteIfEmpty(true); + writer.setHeaderCallback(new StaxWriterCallback() { + + @Override + public void write(XMLEventWriter writer) throws IOException { + XMLEventFactory factory = XMLEventFactory.newInstance(); + try { + writer.add(factory.createStartElement("", "", "header")); + writer.add(factory.createEndElement("", "", "header")); + } + catch (XMLStreamException e) { + throw new RuntimeException(e); + } + + } + + }); + writer.setFooterCallback(new StaxWriterCallback() { + + @Override + public void write(XMLEventWriter writer) throws IOException { + XMLEventFactory factory = XMLEventFactory.newInstance(); + try { + writer.add(factory.createStartElement("", "", "footer")); + writer.add(factory.createEndElement("", "", "footer")); + } + catch (XMLStreamException e) { + throw new RuntimeException(e); + } + + } + + }); + writer.open(executionContext); + writer.update(executionContext); + writer.close(); + assertFalse("file should be deleted" + resource, resource.getFile().exists()); + writer.open(executionContext); + writer.write(items); + writer.update(executionContext); + writer.close(); + String content = getOutputFileContent(); + assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); + } + /** * Item is written to the output file with namespace.