diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java index 5e96331fb..6068fca74 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java @@ -173,6 +173,8 @@ public class FaultTolerantChunkProcessor extends SimpleChunkProcessor implements ChunkProcessor, Initializi throw e; } } + + /** + * Call the listener's after write method. + * + * @param items + */ + protected final void doAfterWrite(List items) + { + listener.afterWrite(items); + } protected void writeItems(List items) throws Exception { itemWriter.write(items); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java index 2e0e36d9d..3d7bd61e1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java @@ -1,6 +1,7 @@ package org.springframework.batch.core.step.item; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; @@ -20,7 +21,7 @@ import org.springframework.batch.retry.policy.NeverRetryPolicy; public class FaultTolerantChunkProcessorTests { - private BatchRetryTemplate batchRetryTemplate = new BatchRetryTemplate(); + private BatchRetryTemplate batchRetryTemplate; private List list = new ArrayList(); @@ -32,6 +33,7 @@ public class FaultTolerantChunkProcessorTests { @Before public void setUp() { + batchRetryTemplate = new BatchRetryTemplate(); processor = new FaultTolerantChunkProcessor(new PassThroughItemProcessor(), new ItemWriter() { public void write(List items) throws Exception { @@ -75,14 +77,14 @@ public class FaultTolerantChunkProcessorTests { processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); try { processor.process(contribution, chunk); - } - catch (RuntimeException e) { + fail(); + } catch (RuntimeException e) { assertEquals("Planned failure!", e.getMessage()); } try { processor.process(contribution, chunk); - } - catch (RuntimeException e) { + fail(); + } catch (RuntimeException e) { assertEquals("Planned failure!", e.getMessage()); } assertEquals(2, chunk.getItems().size()); @@ -94,4 +96,36 @@ public class FaultTolerantChunkProcessorTests { assertEquals(2, after.size()); } + @Test + public void testAfterWriteAllPassedInRecovery() throws Exception { + Chunk chunk = new Chunk(Arrays.asList("foo", "bar")); + processor = new FaultTolerantChunkProcessor(new PassThroughItemProcessor(), + new ItemWriter() { + public void write(List items) throws Exception { + // Fail is there is more than one item + if (items.size() > 1) { + throw new RuntimeException("Planned failure!"); + } + list.addAll(items); + } + }, batchRetryTemplate); + processor.setListeners(Arrays.asList(new ItemListenerSupport() { + @Override + public void afterWrite(List item) { + after.addAll(item); + } + })); + processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); + + try { + processor.process(contribution, chunk); + fail(); + } catch (RuntimeException e) { + assertEquals("Planned failure!", e.getMessage()); + } + processor.process(contribution, chunk); + + assertEquals("[foo, bar]", list.toString()); + assertEquals("[foo, bar]", after.toString()); + } }