diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTasklet.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxy.java similarity index 75% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTasklet.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxy.java index 182ac5d4a..6bb7e7e48 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTasklet.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxy.java @@ -17,36 +17,28 @@ package org.springframework.batch.sample.tasklet; -import org.springframework.batch.core.tasklet.Tasklet; -import org.springframework.batch.execution.tasklet.ItemOrientedTasklet; import org.springframework.batch.io.exception.BatchCriticalException; -import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.item.ItemReader; /** - * Hacked {@link Tasklet} that throws exception on a given record number + * Hacked {@link ItemReader} that throws exception on a given record number * (useful for testing restart). * * @author Robert Kasanicky + * @author Lucas Ward * */ -public class ExceptionRestartableTasklet extends ItemOrientedTasklet { +public class ExceptionThrowingItemReaderProxy implements ItemReader { private int counter = 0; private int throwExceptionOnRecordNumber = 4; - /* (non-Javadoc) - * @see Tasklet#execute() - */ - public ExitStatus execute() throws Exception { - - counter++; - if (counter == throwExceptionOnRecordNumber) { - throw new BatchCriticalException("Planned failure on count="+counter); - } - - return super.execute(); + private final ItemReader itemReader; + + public ExceptionThrowingItemReaderProxy(ItemReader itemReader) { + this.itemReader = itemReader; } - + /** * @param throwExceptionOnRecordNumber The number of record on which exception should be thrown */ @@ -58,4 +50,14 @@ public class ExceptionRestartableTasklet extends ItemOrientedTasklet { return throwExceptionOnRecordNumber; } + public Object read() throws Exception { + + counter++; + if (counter == throwExceptionOnRecordNumber) { + throw new BatchCriticalException("Planned failure on count="+counter); + } + + return itemReader.read(); + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeTasklet.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeWriter.java similarity index 75% rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeTasklet.java rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeWriter.java index de1352262..1458aa5a8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeTasklet.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/tasklet/SimpleTradeWriter.java @@ -17,13 +17,12 @@ package org.springframework.batch.sample.tasklet; import org.springframework.batch.core.tasklet.Tasklet; -import org.springframework.batch.execution.tasklet.ItemOrientedTasklet; -import org.springframework.batch.io.file.DefaultFlatFileItemReader; import org.springframework.batch.item.ExecutionAttributes; import org.springframework.batch.item.ExecutionAttributesProvider; -import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.dao.TradeDao; import org.springframework.batch.sample.domain.Trade; +import org.springframework.util.Assert; /** * Simple implementation of a {@link Tasklet}, which illustrates the reading @@ -39,12 +38,7 @@ import org.springframework.batch.sample.domain.Trade; * @author Lucas Ward * @author Dave Syer */ -public class SimpleTradeTasklet implements Tasklet, ExecutionAttributesProvider { - - /* - * reads the data from input file - */ - private DefaultFlatFileItemReader inputSource; +public class SimpleTradeWriter implements ItemWriter, ExecutionAttributesProvider { /* * writes a Trade object to output @@ -62,21 +56,10 @@ public class SimpleTradeTasklet implements Tasklet, ExecutionAttributesProvider * processed. Because this is a simple example job, the data is simply * written out without any processing. */ - public ExitStatus execute() throws Exception { - Trade trade = (Trade)inputSource.read(); - - if (trade == null) { - // no Trade object returned, reading input is finished - return ExitStatus.FINISHED; - } - + public void write(Object item) throws Exception { + Assert.isInstanceOf(Trade.class, item, "Only items of type: [" + Trade.class + "] are supported by this writer"); tradeCount++; - tradeDao.writeTrade(trade); - return ExitStatus.CONTINUABLE; - } - - public void setItemReader(DefaultFlatFileItemReader inputTemplate) { - this.inputSource = inputTemplate; + tradeDao.writeTrade((Trade)item); } public void setTradeDao(TradeDao tradeDao) { diff --git a/spring-batch-samples/src/main/resources/jobs/parallelJob.xml b/spring-batch-samples/src/main/resources/jobs/parallelJob.xml index 3db6e0106..2d057c527 100644 --- a/spring-batch-samples/src/main/resources/jobs/parallelJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/parallelJob.xml @@ -16,60 +16,50 @@ - + - - - - - - - - - - - - - - - + class="org.springframework.batch.item.reader.ValidatingItemReader"> + + + + + + + + + + + - + - + - - - - - - - - - - - + class="org.springframework.batch.sample.item.reader.StagingItemReader" + scope="step"> + + + + + + + diff --git a/spring-batch-samples/src/main/resources/jobs/restartSample.xml b/spring-batch-samples/src/main/resources/jobs/restartSample.xml index a9cc1ef05..e5818da97 100644 --- a/spring-batch-samples/src/main/resources/jobs/restartSample.xml +++ b/spring-batch-samples/src/main/resources/jobs/restartSample.xml @@ -1,60 +1,64 @@ - - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -64,21 +68,24 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/simpleTaskletJob.xml b/spring-batch-samples/src/main/resources/jobs/simpleTaskletJob.xml index 33643e005..dc1695dd7 100644 --- a/spring-batch-samples/src/main/resources/jobs/simpleTaskletJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/simpleTaskletJob.xml @@ -14,11 +14,10 @@ - - - + + + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTaskletTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java similarity index 58% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTaskletTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java index 660f3097d..c14e95dba 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionRestartableTaskletTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java @@ -11,7 +11,7 @@ import org.springframework.batch.item.reader.ListItemReader; import org.springframework.batch.repeat.context.RepeatContextSupport; import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; -public class ExceptionRestartableTaskletTests extends TestCase { +public class ExceptionThrowingItemReaderProxyTests extends TestCase { //expected call count before exception is thrown (exception should be thrown in next iteration) private static final int ITER_COUNT = 5; @@ -21,23 +21,9 @@ public class ExceptionRestartableTaskletTests extends TestCase { } public void testProcess() throws Exception { - - //create mock item processor which will be called by module.process() method - MockControl processorControl = MockControl.createControl(ItemWriter.class); - ItemWriter itemProcessor = (ItemWriter)processorControl.getMock(); - - //set expected call count and argument matcher - itemProcessor.write(null); - processorControl.setMatcher(MockControl.ALWAYS_MATCHER); - processorControl.setVoidCallable(ITER_COUNT); - processorControl.replay(); - + //create module and set item processor and iteration count - ExceptionRestartableTasklet module = new ExceptionRestartableTasklet(); - module.setItemWriter(itemProcessor); - module.setThrowExceptionOnRecordNumber(ITER_COUNT + 1); - - module.setItemReader(new ListItemReader(new ArrayList() {{ + ExceptionThrowingItemReaderProxy itemReader = new ExceptionThrowingItemReaderProxy(new ListItemReader(new ArrayList() {{ add("a"); add("b"); add("c"); @@ -45,20 +31,20 @@ public class ExceptionRestartableTaskletTests extends TestCase { add("e"); add("f"); }})); + + itemReader.setThrowExceptionOnRecordNumber(ITER_COUNT + 1); RepeatSynchronizationManager.register(new RepeatContextSupport(null)); //call process method multiple times and verify whether exception is thrown when expected for (int i = 0; i <= ITER_COUNT; i++) { try { - module.execute(); + itemReader.read(); assertTrue(i < ITER_COUNT); } catch (BatchCriticalException bce) { assertEquals(ITER_COUNT,i); } } - //verify method calls - processorControl.verify(); } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java index f706bda6b..47e952ee0 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java @@ -44,19 +44,14 @@ public class SimpleTradeTaskletTests extends TestCase { }; //create module - SimpleTradeTasklet module = new SimpleTradeTasklet(); - module.setItemReader(input); + SimpleTradeWriter module = new SimpleTradeWriter(); module.setTradeDao(dao); - //call tested methods - //read method should return true, because input returned fieldset - assertTrue(module.execute().isContinuable()); + module.write(input.read()); //verify whether input and writer were called assertTrue(inputCalled); assertTrue(writerCalled); - //read should return false, because input returned null - assertFalse(module.execute().isContinuable()); } }