diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java
index b67d12fb3..2194f47f3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java
@@ -16,8 +16,8 @@
package org.springframework.batch.core;
/**
- * Represents a contribution to a {@link StepExecution}, buffering changes
- * until they can be applied at a chunk boundary.
+ * Represents a contribution to a {@link StepExecution}, buffering changes until
+ * they can be applied at a chunk boundary.
*
* @author Dave Syer
*
@@ -34,8 +34,6 @@ public class StepContribution {
private volatile int writeSkipCount;
- private volatile int uncommitedReadSkipCount;
-
/**
* @param execution
*/
@@ -76,17 +74,16 @@ public class StepContribution {
/**
* @return the sum of skips accumulated in the parent {@link StepExecution}
- * and this StepContribution, including uncommitted read
- * skips.
+ * and this StepContribution.
*/
public int getStepSkipCount() {
- return uncommitedReadSkipCount + readSkipCount + writeSkipCount + parentSkipCount;
+ return readSkipCount + writeSkipCount + parentSkipCount;
}
/**
* @return the number of skips collected in this
* StepContribution (not including skips accumulated in the
- * parent {@link StepExecution}.
+ * parent {@link StepExecution}).
*/
public int getSkipCount() {
return readSkipCount + writeSkipCount;
@@ -95,10 +92,17 @@ public class StepContribution {
/**
* Increment the read skip count for this contribution
*/
- public void incrementReadsSkipCount() {
+ public void incrementReadSkipCount() {
readSkipCount++;
}
+ /**
+ * Increment the read skip count for this contribution
+ */
+ public void incrementReadSkipCount(int count) {
+ readSkipCount += count;
+ }
+
/**
* Increment the write skip count for this contribution
*/
@@ -106,13 +110,6 @@ public class StepContribution {
writeSkipCount++;
}
- /**
- * Increment the counter for temporary skipped reads
- */
- public void incrementTemporaryReadSkipCount() {
- uncommitedReadSkipCount++;
- }
-
/**
* @return the read skip count
*/
@@ -127,22 +124,14 @@ public class StepContribution {
return writeSkipCount;
}
- /**
- * Add the temporary read skip count to read skip count and reset the
- * temporary counter.
- */
- public void combineSkipCounts() {
- readSkipCount += uncommitedReadSkipCount;
- uncommitedReadSkipCount = 0;
- }
-
/*
* (non-Javadoc)
+ *
* @see java.lang.Object#toString()
*/
public String toString() {
- return "[StepContribution: items=" + itemCount + ", commits=" + commitCount + ", uncommitedReadSkips="
- + uncommitedReadSkipCount + ", readSkips=" + readSkipCount + "writeSkips=" + writeSkipCount + "]";
+ return "[StepContribution: items=" + itemCount + ", commits=" + commitCount + ", readSkips=" + readSkipCount
+ + ", writeSkips=" + writeSkipCount + "]";
}
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java
index 59c4da654..436e6aaf4 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java
@@ -19,8 +19,6 @@ package org.springframework.batch.core;
import java.util.Date;
import org.springframework.batch.item.ExecutionContext;
-import org.springframework.batch.item.ItemReader;
-import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.util.Assert;
@@ -56,7 +54,7 @@ public class StepExecution extends Entity {
private volatile Date startTime = new Date(System.currentTimeMillis());
private volatile Date endTime = null;
-
+
private volatile Date lastUpdated = null;
private volatile ExecutionContext executionContext = new ExecutionContext();
@@ -311,8 +309,6 @@ public class StepExecution extends Entity {
public synchronized void apply(StepContribution contribution) {
itemCount += contribution.getItemCount();
commitCount += contribution.getCommitCount();
-
- contribution.combineSkipCounts();
readSkipCount += contribution.getReadSkipCount();
writeSkipCount += contribution.getWriteSkipCount();
}
@@ -347,7 +343,7 @@ public class StepExecution extends Entity {
}
/**
- * Increment the number of items skipped in the {@link ItemReader}
+ * Increment the number of items skipped on read
*
* @param count - the number of skips to increment by.
*/
@@ -356,7 +352,7 @@ public class StepExecution extends Entity {
}
/**
- * Increment the number of items skipped in the {@link ItemWriter}
+ * Increment the number of items skipped on write
*
* @param count - the number of skips to increment by.
*/
@@ -378,21 +374,21 @@ public class StepExecution extends Entity {
}
/**
- * @return the number of records skipped in the {@link ItemReader}
+ * @return the number of records skipped on read
*/
public int getReadSkipCount() {
return readSkipCount;
}
/**
- * @return the number of records skipped in the {@link ItemWriter}
+ * @return the number of records skipped on write
*/
public int getWriteSkipCount() {
return writeSkipCount;
}
/**
- * Set the number of records skipped in the {@link ItemReader}
+ * Set the number of records skipped on read
*
* @param readSkipCount
*/
@@ -401,7 +397,7 @@ public class StepExecution extends Entity {
}
/**
- * Set the number of records skipped in the {@link ItemWriter}
+ * Set the number of records skipped on write
*
* @param writeSkipCount
*/
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStepHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStepHandler.java
index 82092fa79..d22953ef2 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStepHandler.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ItemOrientedStepHandler.java
@@ -15,7 +15,10 @@
*/
package org.springframework.batch.core.step.item;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -29,7 +32,7 @@ import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatCallback;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatOperations;
-import org.springframework.batch.repeat.support.RepeatTemplate;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Simplest possible implementation of {@link StepHandler} with no skipping or
@@ -81,31 +84,74 @@ public class ItemOrientedStepHandler implements StepHandler {
*/
public ExitStatus handle(final StepContribution contribution) throws Exception {
- ExitStatus result = repeatOperations.iterate(new RepeatCallback() {
- public ExitStatus doInIteration(final RepeatContext context) throws Exception {
- boolean processed = false;
- while (!processed) {
- T item = read(contribution);
+ final List> buffer = getItemBuffer();
+
+ ExitStatus result = ExitStatus.CONTINUABLE;
+
+ if (buffer.isEmpty()) {
+
+ result = repeatOperations.iterate(new RepeatCallback() {
+ public ExitStatus doInIteration(final RepeatContext context) throws Exception {
+ ReadWrapper item = read(contribution);
if (item == null) {
return ExitStatus.FINISHED;
}
- // TODO: segregate read / write / filter count
- contribution.incrementItemCount();
- processed = write(item, contribution);
+ contribution.incrementReadSkipCount(item.getSkipCount());
+ buffer.add(item);
+ return ExitStatus.CONTINUABLE;
}
- return ExitStatus.CONTINUABLE;
- }
- });
+ });
+ }
+
+ List processed = new ArrayList();
+
+ for (Iterator> iterator = buffer.iterator(); iterator.hasNext();) {
+
+ ReadWrapper item = iterator.next();
+ S output = null;
+
+ // TODO: segregate read / write / filter count
+ // (this is read count)
+ contribution.incrementItemCount();
+ // TODO: processor listener
+ output = itemProcessor.process(item.getItem());
+
+ // TODO: increment filter count if this is null
+ if (output != null) {
+ processed.add(output);
+ }
+
+ }
+
+ // TODO: use ItemWriter interface properly
+ // TODO: make sure exceptions get handled by the appropriate handler
+ for (S data : processed) {
+ write(data, contribution);
+ }
+ buffer.clear();
+
+ logger.info("Contribution: " + contribution);
return result;
+
+ }
+
+ private List> getItemBuffer() {
+ if (!TransactionSynchronizationManager.hasResource(this)) {
+ TransactionSynchronizationManager.bindResource(this, new ArrayList>());
+ }
+ @SuppressWarnings("unchecked")
+ List> resource = (List>) TransactionSynchronizationManager.getResource(this);
+ return resource;
}
/**
* @param contribution current context
* @return next item for writing
*/
- protected T read(StepContribution contribution) throws Exception {
- return doRead();
+ protected ReadWrapper read(StepContribution contribution) throws Exception {
+ T item = doRead();
+ return item==null ? null : new ReadWrapper(item);
}
/**
@@ -120,24 +166,18 @@ public class ItemOrientedStepHandler implements StepHandler {
*
* @param item the item to write
* @param contribution current context
- * @return true if the item was written (as opposed to filtered)
*/
- protected boolean write(T item, StepContribution contribution) throws Exception {
- return doWrite(item);
+ protected void write(S item, StepContribution contribution) throws Exception {
+ doWrite(item);
}
/**
* @param item
* @throws Exception
*/
- protected final boolean doWrite(T item) throws Exception {
- S processed = itemProcessor.process(item);
- if (processed != null) {
- // TODO: increment filtered item count
- itemWriter.write(Collections.singletonList(processed));
- return true;
- }
- return false;
+ protected final void doWrite(S item) throws Exception {
+ // TODO: increment write count
+ itemWriter.write(Collections.singletonList(item));
}
/**
@@ -154,4 +194,47 @@ public class ItemOrientedStepHandler implements StepHandler {
itemReader.reset();
}
+ /**
+ * @author Dave Syer
+ *
+ */
+ static protected class ReadWrapper {
+
+ final private T item;
+
+ final private int skipCount;
+
+ /**
+ * @param item
+ */
+ public ReadWrapper(T item) {
+ this(item, 0);
+ }
+
+ /**
+ * @param item
+ * @param skipCount
+ */
+ public ReadWrapper(T item, int skipCount) {
+ this.item = item;
+ this.skipCount = skipCount;
+ }
+
+ /**
+ * @return the item we are wrapping
+ */
+ public T getItem() {
+ return item;
+ }
+
+ /**
+ * Public getter for the skipCount.
+ * @return the skipCount
+ */
+ public int getSkipCount() {
+ return skipCount;
+ }
+
+ }
+
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java
index 1a8ace076..1a3c96879 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java
@@ -368,22 +368,25 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean
* count
* @return next item for processing
*/
- protected T read(StepContribution contribution) throws Exception {
+ protected ReadWrapper read(StepContribution contribution) throws Exception {
+
+ int skipCount = 0;
while (true) {
try {
- return doRead();
+ T item = doRead();
+ return item==null ? null : new ReadWrapper(item, skipCount);
}
catch (Exception e) {
try {
if (readSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) {
// increment skip count and try again
- contribution.incrementTemporaryReadSkipCount();
try {
+ skipCount++;
listener.onSkipInRead(e);
}
catch (RuntimeException ex) {
- contribution.combineSkipCounts();
+ contribution.incrementReadSkipCount(skipCount);
throw new SkipListenerFailedException("Fatal exception in SkipListener.", ex, e);
}
logger.debug("Skipping failed input", e);
@@ -397,7 +400,7 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean
catch (SkipLimitExceededException ex) {
// we are headed for a abnormal ending so bake in the
// skip count
- contribution.combineSkipCounts();
+ contribution.incrementReadSkipCount(skipCount);
throw ex;
}
}
@@ -413,10 +416,12 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean
* exhausted. The listener callback (on write failure) will happen in
* the next transaction automatically.
*/
- protected boolean write(final T item, final StepContribution contribution) throws Exception {
+ @Override
+ protected void write(final S item, final StepContribution contribution) throws Exception {
RecoveryRetryCallback retryCallback = new RecoveryRetryCallback(item, new RetryCallback() {
public Object doWithRetry(RetryContext context) throws Throwable {
- return doWrite(item);
+ doWrite(item);
+ return null;
}
}, itemKeyGenerator != null ? itemKeyGenerator.getKey(item) : item);
retryCallback.setRecoveryCallback(new RecoveryCallback() {
@@ -431,10 +436,10 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean
throw new SkipListenerFailedException("Fatal exception in SkipListener.", ex, t);
}
}
- return true;
+ return null;
}
});
- return (Boolean) retryOperations.execute(retryCallback);
+ retryOperations.execute(retryCallback);
}
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ItemOrientedStepHandlerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ItemOrientedStepHandlerTests.java
index 3a5442450..73cc2f89e 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ItemOrientedStepHandlerTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ItemOrientedStepHandlerTests.java
@@ -71,8 +71,8 @@ public class ItemOrientedStepHandlerTests {
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
handler.handle(contribution);
- assertEquals(4, itemReader.count);
- assertEquals("1234", itemWriter.values);
+ assertEquals(2, itemReader.count);
+ assertEquals("12", itemWriter.values);
}
/**
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java
index 256f044ff..25d517dae 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java
@@ -46,13 +46,9 @@ import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
-import org.springframework.batch.repeat.RepeatContext;
-import org.springframework.batch.repeat.exception.ExceptionHandler;
import org.springframework.batch.repeat.exception.SimpleLimitExceptionHandler;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
-import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
-import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
/**
@@ -131,22 +127,6 @@ public class SimpleStepFactoryBeanTests {
@Test
public void testSimpleJobWithItemListeners() throws Exception {
- final List throwables = new ArrayList();
-
- RepeatTemplate chunkOperations = new RepeatTemplate();
- // Always handle the exception to check it is the right one...
- chunkOperations.setExceptionHandler(new ExceptionHandler() {
- public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException {
- throwables.add(throwable);
- assertEquals("Error!", throwable.getMessage());
- }
- });
-
- /*
- * Each message fails once and the chunk (size=1) "rolls back"; then it
- * is recovered ("skipped") on the second attempt (see retry policy
- * definition above)...
- */
SimpleStepFactoryBean factory = getStepFactory(new String[] { "foo", "bar", "spam" });
factory.setItemWriter(new ItemWriter() {
@@ -164,19 +144,24 @@ public class SimpleStepFactoryBeanTests {
}
} });
- factory.setChunkOperations(chunkOperations);
- StepHandlerStep step = (StepHandlerStep) factory.getObject();
+ Step step = (Step) factory.getObject();
- job.setSteps(Collections.singletonList((Step) step));
+ job.setSteps(Collections.singletonList(step));
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
- job.execute(jobExecution);
+ try {
+ job.execute(jobExecution);
+ fail("Expected RuntimeException");
+ } catch (RuntimeException e) {
+ // expected
+ assertEquals("Error!", e.getMessage());
+ }
- assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
assertEquals(0, written.size());
- // provider should be exhausted
- assertEquals(null, reader.read());
- assertEquals(3, recovered.size());
+ // provider should be at second item
+ assertEquals("bar", reader.read());
+ assertEquals(1, recovered.size());
}
@Test
@@ -313,7 +298,7 @@ public class SimpleStepFactoryBeanTests {
private SimpleStepFactoryBean getStepFactory(String... args) throws Exception {
SimpleStepFactoryBean factory = new SimpleStepFactoryBean();
- List items = TransactionAwareProxyFactory.createTransactionalList();
+ List items = new ArrayList();
items.addAll(Arrays.asList(args));
reader = new ListItemReader(items);
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBeanTests.java
index 0842a28b0..2ee359c3f 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBeanTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBeanTests.java
@@ -1,27 +1,30 @@
package org.springframework.batch.core.step.item;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import junit.framework.TestCase;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+import org.junit.Test;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.listener.SkipListenerSupport;
-import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.core.step.JobRepositorySupport;
import org.springframework.batch.core.step.skip.SkipLimitExceededException;
import org.springframework.batch.core.step.skip.SkipListenerFailedException;
-import org.springframework.batch.item.ClearFailedException;
-import org.springframework.batch.item.FlushFailedException;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.MarkFailedException;
@@ -38,7 +41,7 @@ import org.springframework.util.StringUtils;
/**
* Tests for {@link SkipLimitStepFactoryBean}.
*/
-public class SkipLimitStepFactoryBeanTests extends TestCase {
+public class SkipLimitStepFactoryBeanTests {
protected final Log logger = LogFactory.getLog(getClass());
@@ -58,7 +61,8 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
protected int count;
- protected void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
factory.setBeanName("stepName");
factory.setJobRepository(new JobRepositorySupport());
factory.setTransactionManager(new ResourcelessTransactionManager());
@@ -75,8 +79,10 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
+ @Test
public void testSkip() throws Exception {
- AbstractStep step = (AbstractStep) factory.getObject();
+
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
step.execute(stepExecution);
@@ -103,13 +109,14 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
* Check skippable write exception does not cause rollback when included on
* transaction attributes as "no rollback for".
*/
+ @Test
public void testSkipWithoutRethrow() throws Exception {
factory.setTransactionAttribute(new DefaultTransactionAttribute() {
public boolean rollbackOn(Throwable ex) {
return !(ex instanceof SkippableRuntimeException);
};
});
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
step.execute(stepExecution);
@@ -129,6 +136,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
* Fatal exception should cause immediate termination regardless of other
* skip settings (note the fatal exception is also classified as skippable).
*/
+ @Test
public void testFatalException() throws Exception {
factory.setFatalExceptionClasses(new Class[] { FatalRuntimeException.class });
factory.setItemWriter(new SkipWriterStub() {
@@ -137,7 +145,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
}
});
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
try {
@@ -152,11 +160,12 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
+ @Test
public void testSkipOverLimit() throws Exception {
factory.setSkipLimit(1);
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
@@ -182,17 +191,17 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
- @SuppressWarnings("unchecked")
+ @Test
public void testSkipOverLimitOnRead() throws Exception {
- reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), StringUtils
- .commaDelimitedListToSet("2,3,5"));
+ reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
+ .asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(3);
factory.setItemReader(reader);
factory.setSkippableExceptionClasses(new Class[] { Exception.class });
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
@@ -224,11 +233,11 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
- @SuppressWarnings("unchecked")
+ @Test
public void testSkipListenerFailsOnRead() throws Exception {
- reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), StringUtils
- .commaDelimitedListToSet("2,3,5"));
+ reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
+ .asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(3);
factory.setItemReader(reader);
@@ -240,7 +249,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
} });
factory.setSkippableExceptionClasses(new Class[] { Exception.class });
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
@@ -261,11 +270,11 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
- @SuppressWarnings("unchecked")
+ @Test
public void testSkipListenerFailsOnWrite() throws Exception {
- reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), StringUtils
- .commaDelimitedListToSet("2,3,5"));
+ reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
+ .asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(3);
factory.setItemReader(reader);
@@ -277,7 +286,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
} });
factory.setSkippableExceptionClasses(new Class[] { Exception.class });
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
@@ -289,8 +298,8 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
assertEquals("oops", e.getCause().getMessage());
}
- assertEquals(1, stepExecution.getSkipCount());
- assertEquals(0, stepExecution.getReadSkipCount());
+ assertEquals(3, stepExecution.getSkipCount());
+ assertEquals(2, stepExecution.getReadSkipCount());
assertEquals(1, stepExecution.getWriteSkipCount());
}
@@ -298,16 +307,16 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
- @SuppressWarnings("unchecked")
+ @Test
public void testSkipOnReadNotDoubleCounted() throws Exception {
- reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), StringUtils
- .commaDelimitedListToSet("2,3,5"));
+ reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
+ .asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(4);
factory.setItemReader(reader);
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = jobExecution.createStepExecution(step);
@@ -325,19 +334,19 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Check items causing errors are skipped as expected.
*/
- @SuppressWarnings("unchecked")
+ @Test
public void testSkipOnWriteNotDoubleCounted() throws Exception {
- reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7"), StringUtils
- .commaDelimitedListToSet("2,3"));
+ reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7"), Arrays
+ .asList(StringUtils.commaDelimitedListToStringArray("2,3")));
- writer = new SkipWriterStub(StringUtils.commaDelimitedListToSet("4,5"));
+ writer = new SkipWriterStub(Arrays.asList(StringUtils.commaDelimitedListToStringArray("4,5")));
factory.setSkipLimit(4);
factory.setItemReader(reader);
factory.setItemWriter(writer);
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = jobExecution.createStepExecution(step);
@@ -354,15 +363,14 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
}
- @SuppressWarnings("unchecked")
+ @Test
public void testDefaultSkipPolicy() throws Exception {
factory.setSkippableExceptionClasses(new Class[] { Exception.class });
factory.setSkipLimit(1);
- List items = TransactionAwareProxyFactory.createTransactionalList();
- items.addAll(Arrays.asList(new String[] { "a", "b", "c" }));
- ItemReader provider = new ListItemReader(items) {
- public Object read() {
- Object item = super.read();
+ List items = Arrays.asList(new String[] { "a", "b", "c" });
+ ItemReader provider = new ListItemReader(items) {
+ public String read() {
+ String item = super.read();
count++;
if ("b".equals(item)) {
throw new RuntimeException("Read error - planned failure.");
@@ -371,7 +379,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
}
};
factory.setItemReader(provider);
- AbstractStep step = (AbstractStep) factory.getObject();
+ Step step = (Step) factory.getObject();
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
step.execute(stepExecution);
@@ -381,6 +389,8 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
assertEquals(4, count);
}
+ // TODO: test with transactional reader (e.g. list with tx proxy)
+
/**
* Simple item reader that supports skip functionality.
*/
@@ -394,8 +404,6 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
private int counter = -1;
- private int marked = 0;
-
private final Collection failures;
public SkipReaderStub() {
@@ -424,13 +432,9 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
}
public void mark() throws MarkFailedException {
- logger.debug("Marked at count=" + counter);
- marked = counter;
}
public void reset() throws ResetFailedException {
- counter = marked;
- logger.debug("Reset at count=" + counter);
}
}
@@ -442,6 +446,7 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
protected final Log logger = LogFactory.getLog(getClass());
+ // simulate transactional output
private List