From 7c19e7aef36cc3ab1f49e0b1d755dbae0065b1b2 Mon Sep 17 00:00:00 2001 From: dsyer Date: Tue, 19 Jan 2010 10:08:14 +0000 Subject: [PATCH] RESOLVED - issue BATCH-1490: StaxEventItemWriter outputs invalid xml if step handling is failed and retried when handling the first chunk of data --- .../batch/item/xml/StaxEventItemWriter.java | 5 ++ .../item/xml/StaxEventItemWriterTests.java | 55 ++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) 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 e2b77a899..1390222da 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 @@ -459,6 +459,11 @@ public class StaxEventItemWriter extends ExecutionContextUserSupport implemen } + /* + * This forces the flush to write the end of the root element and avoids + * an off-by-one error on restart. + */ + writer.add(factory.createIgnorableSpace("")); writer.flush(); } 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 59ab20962..4d4fcd69f 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 @@ -162,6 +162,60 @@ public class StaxEventItemWriterTests { assertTrue(outputFile.contains("" + TEST_STRING + TEST_STRING + "")); } + @Test + public void testTransactionalRestartFailOnFirstWrite() throws Exception { + + PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); + + writer.open(executionContext); + try { + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + public Object doInTransaction(TransactionStatus status) { + try { + writer.write(items); + } + catch (Exception e) { + throw new IllegalStateException("Could not write data", e); + } + throw new UnexpectedInputException("Could not write data"); + } + }); + } + catch (UnexpectedInputException e) { + // expected + } + writer.close(); + System.err.println(getOutputFileContent()); + String outputFile = getOutputFileContent(); + assertEquals("", outputFile); + + // create new writer from saved restart data and continue writing + writer = createItemWriter(); + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + public Object doInTransaction(TransactionStatus status) { + writer.open(executionContext); + try { + writer.write(items); + } + catch (Exception e) { + throw new UnexpectedInputException("Could not write data", e); + } + // get restart data + writer.update(executionContext); + return null; + } + }); + writer.close(); + + // check the output is concatenation of 'before restart' and 'after + // restart' writes. + outputFile = getOutputFileContent(); + System.err.println(getOutputFileContent()); + assertEquals(1, StringUtils.countOccurrencesOf(outputFile, TEST_STRING)); + assertTrue(outputFile.contains("" + TEST_STRING + "")); + assertEquals("", outputFile); + } + /** * Item is written to the output file only after flush. */ @@ -324,7 +378,6 @@ public class StaxEventItemWriterTests { writer.write(items); writer.close(); String content = getOutputFileContent(); - System.err.println(content); assertTrue("Wrong content: " + content, content .contains(("")));