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 4e8e351f3..fd3bb5c1c 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 @@ -142,6 +142,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { private boolean forceSync; + private boolean shouldDeleteIfEmpty = false; + public StaxEventItemWriter() { setExecutionContextName(ClassUtils.getShortName(StaxEventItemWriter.class)); } @@ -203,6 +205,16 @@ ResourceAwareItemWriterItemStream, InitializingBean { this.forceSync = forceSync; } + /** + * Flag to indicate that the target file should be deleted if no items have + * been written (other than header and footer) on close. Defaults to false. + * + * @param shouldDeleteIfEmpty the flag value to set + */ + public void setShouldDeleteIfEmpty(boolean shouldDeleteIfEmpty) { + this.shouldDeleteIfEmpty = shouldDeleteIfEmpty; + } + /** * Get used encoding. * @@ -354,6 +366,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { // otherwise start from beginning if (executionContext.containsKey(getExecutionContextKey(RESTART_DATA_NAME))) { startAtPosition = executionContext.getLong(getExecutionContextKey(RESTART_DATA_NAME)); + currentRecordCount = executionContext.getLong(getExecutionContextKey(WRITE_STATISTICS_NAME)); restarted = true; } @@ -656,6 +669,14 @@ ResourceAwareItemWriterItemStream, InitializingBean { } } } + if (currentRecordCount == 0 && shouldDeleteIfEmpty) { + try { + resource.getFile().delete(); + } + catch (IOException e) { + throw new ItemStreamException("Failed to delete empty file on close", e); + } + } } } 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 474935745..7a373ee92 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 @@ -352,6 +352,93 @@ public class StaxEventItemWriterTests { assertEquals("Output resource must exist", e.getMessage()); } } + + /** + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set. + */ + @Test + public void testDeleteIfEmptyRecordsWritten() throws Exception { + writer.setShouldDeleteIfEmpty(true); + writer.open(executionContext); + writer.write(items); + 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. + */ + @Test + public void testDeleteIfEmptyNoRecordsWritten() throws Exception { + writer.setShouldDeleteIfEmpty(true); + writer.open(executionContext); + writer.close(); + assertFalse("file should be deleted" + resource, resource.getFile().exists()); + } + + /** + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set. + */ + @Test + public void testDeleteIfEmptyNoRecordsWrittenHeaderAndFooter() 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.close(); + assertFalse("file should be deleted" + resource, resource.getFile().exists()); + } + + /** + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set. + */ + @Test + public void testDeleteIfEmptyRecordsWrittenRestart() throws Exception { + writer.setShouldDeleteIfEmpty(true); + writer.open(executionContext); + writer.write(items); + writer.update(executionContext); + writer.close(); + + writer = createItemWriter(); + writer.setShouldDeleteIfEmpty(true); + writer.open(executionContext); + writer.close(); + String content = getOutputFileContent(); + assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); + } + /** * Item is written to the output file with namespace.