Extract common inner-classes from FaultTolerantStepFactoryBean*Tests

This commit is contained in:
dhgarrette
2009-05-30 00:27:29 +00:00
parent d035f14f3a
commit a7f8988422
9 changed files with 400 additions and 344 deletions

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
import java.util.Collection;
import java.util.Collections;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public abstract class ExceptionThrowingItemHandlerStub<T> {
private Collection<T> failures = Collections.emptyList();
private boolean runtimeException = false;
public ExceptionThrowingItemHandlerStub() {
}
public ExceptionThrowingItemHandlerStub(Collection<T> failures) {
this.failures = failures;
}
public ExceptionThrowingItemHandlerStub(Collection<T> failures, boolean runtimeException) {
this(failures);
this.runtimeException = runtimeException;
}
public void setFailures(Collection<T> failures) {
this.failures = failures;
}
public void setRuntimeException(boolean runtimeException) {
this.runtimeException = runtimeException;
}
protected void checkFailure(T item) throws Exception {
if (isFailure(item)) {
if (runtimeException) {
throw new SkippableRuntimeException("should cause rollback in reader");
}
else {
throw new SkippableException("shouldn't cause rollback in reader");
}
}
}
protected boolean isFailure(T item) {
return this.failures.contains(item);
}
}

View File

@@ -49,6 +49,8 @@ public class FaultTolerantStepFactoryBeanNonBufferingTests {
private JobExecution jobExecution;
private static final SkippableRuntimeException exception = new SkippableRuntimeException("exception in writer");
int count = 0;
@Before
@@ -74,9 +76,9 @@ public class FaultTolerantStepFactoryBeanNonBufferingTests {
public void testSkip() throws Exception {
@SuppressWarnings("unchecked")
SkipListener<Integer, String> skipListener = createStrictMock(SkipListener.class);
skipListener.onSkipInWrite("3", SkipWriterStub.exception);
skipListener.onSkipInWrite("3", exception);
expectLastCall().once();
skipListener.onSkipInWrite("4", SkipWriterStub.exception);
skipListener.onSkipInWrite("4", exception);
expectLastCall().once();
replay(skipListener);
@@ -114,8 +116,6 @@ public class FaultTolerantStepFactoryBeanNonBufferingTests {
protected final Log logger = LogFactory.getLog(getClass());
private static final SkippableRuntimeException exception = new SkippableRuntimeException("exception in writer");
// simulate transactional output
private List<Object> written = TransactionAwareProxyFactory.createTransactionalList();
@@ -145,16 +145,4 @@ public class FaultTolerantStepFactoryBeanNonBufferingTests {
}
private static class SkippableException extends Exception {
public SkippableException(String message) {
super(message);
}
}
private static class SkippableRuntimeException extends RuntimeException {
public SkippableRuntimeException(String message) {
super(message);
}
}
}

View File

@@ -4,10 +4,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -22,13 +20,7 @@ import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
@@ -44,11 +36,9 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
private FaultTolerantStepFactoryBean<String, String> factory;
private static Collection<String> NO_FAILURES = Collections.emptyList();
private SkipReaderStub<String> reader = new SkipReaderStub<String>("1", "2", "3", "4", "5");
private SkipReaderStub reader = new SkipReaderStub();
private SkipWriterStub writer = new SkipWriterStub();
private SkipWriterStub<String> writer = new SkipWriterStub<String>();
private JobExecution jobExecution;
@@ -56,19 +46,17 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
private JobRepository repository;
private static boolean runtimeException = false;
@Before
public void setUp() throws Exception {
factory = new FaultTolerantStepFactoryBean<String, String>();
factory.setBeanName("stepName");
factory.setTransactionManager(new ResourcelessTransactionManager());
factory.setCommitInterval(2);
factory.setItemReader(reader);
factory.setItemWriter(writer);
factory.setSkipLimit(2);
@SuppressWarnings("unchecked")
Collection<Class<? extends Throwable>> skippableExceptions = Arrays
.<Class<? extends Throwable>> asList(Exception.class);
@@ -121,11 +109,11 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testReaderDefaultNoRollbackOnCheckedException() throws Exception {
factory.setItemReader(new SkipReaderStub(new String[] { "1", "2", "3", "4" }, Arrays.asList("2", "3")));
factory.setItemReader(new SkipReaderStub<String>(new String[] { "1", "2", "3", "4" }, Arrays.asList("2", "3"),
false));
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -137,7 +125,8 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testReaderAttributesOverrideSkippableNoRollback() throws Exception {
factory.setItemReader(new SkipReaderStub(new String[] { "1", "2", "3", "4" }, Arrays.asList("2", "3")));
factory.setItemReader(new SkipReaderStub<String>(new String[] { "1", "2", "3", "4" }, Arrays.asList("2", "3"),
false));
// No skips by default
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>());
@@ -146,7 +135,6 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -159,16 +147,14 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testProcessorDefaultRollbackOnCheckedException() throws Exception {
SkipProcessorStub processor = new SkipProcessorStub(Arrays.asList(StringUtils
.commaDelimitedListToStringArray("1,3")));
SkipProcessorStub<String> processor = new SkipProcessorStub<String>(false, "1", "3");
factory.setItemProcessor(processor);
factory.setItemReader(new SkipReaderStub(new String[] { "1", "2", "3", "4" }, NO_FAILURES));
factory.setItemWriter(new SkipWriterStub(NO_FAILURES));
factory.setItemReader(new SkipReaderStub<String>(new String[] { "1", "2", "3", "4" }));
factory.setItemWriter(new SkipWriterStub<String>());
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -180,16 +166,14 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testProcessorDefaultRollbackOnRuntimeException() throws Exception {
SkipProcessorStub processor = new SkipProcessorStub(Arrays.asList(StringUtils
.commaDelimitedListToStringArray("1,3")));
SkipProcessorStub<String> processor = new SkipProcessorStub<String>(true, "1", "3");
factory.setItemProcessor(processor);
factory.setItemReader(new SkipReaderStub(new String[] { "1", "2", "3", "4" }, NO_FAILURES));
factory.setItemWriter(new SkipWriterStub(NO_FAILURES));
factory.setItemReader(new SkipReaderStub<String>(new String[] { "1", "2", "3", "4" }));
factory.setItemWriter(new SkipWriterStub<String>());
Step step = (Step) factory.getObject();
runtimeException = true;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -199,14 +183,13 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
@Test
public void testProcessSkipWithNoRollbackForCheckedException() throws Exception {
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" });
factory.setItemReader(reader);
factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class));
SkipProcessorStub processor = new SkipProcessorStub(Arrays.asList(new String[] { "4" }));
SkipProcessorStub<String> processor = new SkipProcessorStub<String>(false, "4");
factory.setItemProcessor(processor);
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
@@ -217,11 +200,11 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
assertEquals(0, stepExecution.getRollbackCount());
// skips "4"
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
assertTrue(reader.getRead().contains("4"));
assertFalse(writer.getCommitted().contains("4"));
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
}
@@ -230,11 +213,10 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testWriterDefaultRollbackOnCheckedException() throws Exception {
factory.setItemWriter(new SkipWriterStub(Arrays.asList("2", "3")));
factory.setItemWriter(new SkipWriterStub<String>(false, "2", "3"));
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -246,11 +228,10 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testWriterDefaultRollbackOnRuntimeException() throws Exception {
factory.setItemWriter(new SkipWriterStub(Arrays.asList("2", "3")));
factory.setItemWriter(new SkipWriterStub<String>(true, "2", "3"));
Step step = (Step) factory.getObject();
runtimeException = true;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -263,12 +244,11 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testWriterNoRollbackOnRuntimeException() throws Exception {
factory.setItemWriter(new SkipWriterStub(Arrays.asList("2", "3")));
factory.setItemWriter(new SkipWriterStub<String>(true, "2", "3"));
factory.setNoRollbackExceptionClasses(getExceptionList(SkippableRuntimeException.class));
Step step = (Step) factory.getObject();
runtimeException = true;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -283,12 +263,11 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
*/
@Test
public void testWriterNoRollbackOnCheckedException() throws Exception {
factory.setItemWriter(new SkipWriterStub(Arrays.asList("2", "3")));
factory.setItemWriter(new SkipWriterStub<String>(false, "2", "3"));
factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class));
Step step = (Step) factory.getObject();
runtimeException = false;
step.execute(stepExecution);
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertEquals(2, stepExecution.getSkipCount());
@@ -303,127 +282,4 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
return Arrays.<Class<? extends Throwable>> asList(args);
}
private static class SkipProcessorStub implements ItemProcessor<String, String> {
private final Collection<String> failures;
public SkipProcessorStub() {
this(NO_FAILURES);
}
public SkipProcessorStub(Collection<String> failures) {
this.failures = failures;
}
public String process(String item) throws Exception {
if (failures.contains(item)) {
if (runtimeException) {
throw new SkippableRuntimeException("should cause rollback");
}
else {
throw new SkippableException("shouldn't cause rollback");
}
}
return item;
}
}
/**
* Simple item reader that supports skip functionality.
*/
private static class SkipReaderStub implements ItemReader<String> {
protected final Log logger = LogFactory.getLog(getClass());
private final String[] items;
private Collection<String> processed = new ArrayList<String>();
private int counter = -1;
private final Collection<String> failures;
public SkipReaderStub() {
this(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
}
public SkipReaderStub(String[] items, Collection<String> failures) {
this.items = items;
this.failures = failures;
}
public String read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
logger.debug("Returning null at count=" + counter);
return null;
}
String item = items[counter];
if (failures.contains(item)) {
logger.debug("Throwing exception for [" + item + "] at count=" + counter);
if (runtimeException) {
throw new SkippableRuntimeException("should cause rollback in reader");
}
else {
throw new SkippableException("shouldn't cause rollback in reader");
}
}
processed.add(item);
logger.debug("Returning [" + item + "] at count=" + counter);
return item;
}
}
/**
* Simple item writer that supports skip functionality.
*/
private static class SkipWriterStub implements ItemWriter<String> {
protected final Log logger = LogFactory.getLog(getClass());
// simulate transactional output
private List<Object> written = TransactionAwareProxyFactory.createTransactionalList();
private final Collection<String> failures;
public SkipWriterStub() {
this(NO_FAILURES);
}
/**
* @param failures commaDelimitedListToSet
*/
public SkipWriterStub(Collection<String> failures) {
this.failures = failures;
}
public void write(List<? extends String> items) throws Exception {
for (String item : items) {
if (failures.contains(item)) {
logger.debug("Throwing write exception on [" + item + "]");
if (runtimeException) {
throw new SkippableRuntimeException("should cause rollback in writer");
}
else {
throw new SkippableException("shouldn't cause rollback in writer");
}
}
written.add(item);
}
}
}
private static class SkippableException extends Exception {
public SkippableException(String message) {
super(message);
}
}
private static class SkippableRuntimeException extends RuntimeException {
public SkippableRuntimeException(String message) {
super(message);
}
}
}

View File

@@ -47,7 +47,6 @@ import org.springframework.batch.item.WriteFailedException;
import org.springframework.batch.item.WriterNotOpenException;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.test.util.ReflectionTestUtils;
@@ -62,9 +61,10 @@ public class FaultTolerantStepFactoryBeanTests {
private FaultTolerantStepFactoryBean<String, String> factory;
private SkipReaderStub reader = new SkipReaderStub();
private SkipReaderStub<String> reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" },
Collections.singleton("2"));
private SkipWriterStub writer = new SkipWriterStub();
private SkipWriterStub<String> writer = new SkipWriterStub<String>("4");
private JobExecution jobExecution;
@@ -80,8 +80,6 @@ public class FaultTolerantStepFactoryBeanTests {
private boolean closed = false;
private Collection<String> NO_FAILURES = Collections.emptyList();
@Before
public void setUp() throws Exception {
factory = new FaultTolerantStepFactoryBean<String, String>();
@@ -147,7 +145,7 @@ public class FaultTolerantStepFactoryBeanTests {
factory.setCommitInterval(1);
// no failures on read
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, new ArrayList<String>());
reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" });
factory.setItemReader(reader);
factory.setItemWriter(new ItemWriter<String>() {
@@ -161,7 +159,7 @@ public class FaultTolerantStepFactoryBeanTests {
step.execute(stepExecution);
assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
assertEquals(1, reader.processed.size());
assertEquals(1, reader.getRead().size());
assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode());
assertTrue(stepExecution.getExitStatus().getExitDescription().contains("non-skippable exception"));
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
@@ -174,13 +172,13 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testReadSkip() throws Exception {
writer = new SkipWriterStub(NO_FAILURES);
writer = new SkipWriterStub<String>();
factory.setItemWriter(writer);
Step step = (Step) factory.getObject();
step.execute(stepExecution);
System.err.println(writer.written);
System.err.println(writer.getWritten());
assertEquals(1, stepExecution.getSkipCount());
assertEquals(1, stepExecution.getReadSkipCount());
@@ -189,11 +187,11 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(0, stepExecution.getRollbackCount());
// writer did not skip "2" as it never made it to writer, only "4" did
assertTrue(reader.processed.contains("4"));
assertFalse(reader.processed.contains("2"));
assertTrue(reader.getRead().contains("4"));
assertFalse(reader.getRead().contains("2"));
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3,4,5"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getWritten());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
@@ -206,11 +204,11 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testProcessSkip() throws Exception {
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" });
factory.setItemReader(reader);
writer = new SkipWriterStub(NO_FAILURES);
writer = new SkipWriterStub<String>();
factory.setItemWriter(writer);
SkipProcessorStub processor = new SkipProcessorStub(Arrays.asList(new String[] { "4" }));
SkipProcessorStub<String> processor = new SkipProcessorStub<String>("4");
factory.setItemProcessor(processor);
Step step = (Step) factory.getObject();
@@ -223,11 +221,11 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(1, stepExecution.getRollbackCount());
// writer skips "4"
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
assertTrue(reader.getRead().contains("4"));
assertFalse(writer.getWritten().contains("4"));
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getWritten());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
@@ -237,9 +235,9 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testProcessFilter() throws Exception {
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" });
factory.setItemReader(reader);
writer = new SkipWriterStub(NO_FAILURES);
writer = new SkipWriterStub<String>();
factory.setItemWriter(writer);
FilterProcessorStub processor = new FilterProcessorStub(Arrays.asList(new String[] { "4" }));
factory.setItemProcessor(processor);
@@ -257,11 +255,11 @@ public class FaultTolerantStepFactoryBeanTests {
assertTrue(listenerStub.isFilterEncountered());
// writer skips "4"
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
assertTrue(reader.getRead().contains("4"));
assertFalse(writer.getWritten().contains("4"));
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getWritten());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
@@ -274,7 +272,7 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testWriteSkip() throws Exception {
reader = new SkipReaderStub(new String[] { "1", "2", "3", "4", "5" }, NO_FAILURES);
reader = new SkipReaderStub<String>(new String[] { "1", "2", "3", "4", "5" });
factory.setItemReader(reader);
Step step = (Step) factory.getObject();
@@ -287,11 +285,11 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(2, stepExecution.getRollbackCount());
// writer skips "4"
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
assertTrue(reader.getRead().contains("4"));
assertFalse(writer.getCommitted().contains("4"));
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
@@ -306,7 +304,7 @@ public class FaultTolerantStepFactoryBeanTests {
public void testFatalException() throws Exception {
factory.setFatalExceptionClasses(Collections
.<Class<? extends Throwable>> singleton(FatalRuntimeException.class));
factory.setItemWriter(new SkipWriterStub() {
factory.setItemWriter(new SkipWriterStub<String>() {
public void write(List<? extends String> items) {
throw new FatalRuntimeException("Ouch!");
}
@@ -335,12 +333,12 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(1, stepExecution.getSkipCount());
// writer did not skip "2" as it never made it to writer, only "4" did
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
assertTrue(reader.getRead().contains("4"));
assertFalse(writer.getCommitted().contains("4"));
// failure on "4" tripped the skip limit so we never got to "5"
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
.getName()));
}
@@ -351,7 +349,7 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipOverLimitOnRead() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
reader = new SkipReaderStub<String>(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
.asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(3);
@@ -368,12 +366,12 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(1, stepExecution.getWriteSkipCount());
// writer did not skip "2" as it never made it to writer, only "4" did
assertFalse(reader.processed.contains("2"));
assertTrue(reader.processed.contains("4"));
assertFalse(reader.getRead().contains("2"));
assertTrue(reader.getRead().contains("4"));
// only "1" was ever committed
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
.getName()));
}
@@ -384,7 +382,7 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipListenerFailsOnRead() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
reader = new SkipReaderStub<String>(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
.asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(3);
@@ -419,8 +417,7 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipListenerFailsOnWrite() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Collections
.<String> emptyList());
reader = new SkipReaderStub<String>(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"));
factory.setSkipLimit(3);
factory.setItemReader(reader);
@@ -450,7 +447,7 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipOnReadNotDoubleCounted() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
reader = new SkipReaderStub<String>(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6"), Arrays
.asList(StringUtils.commaDelimitedListToStringArray("2,3,5")));
factory.setSkipLimit(4);
@@ -465,7 +462,7 @@ public class FaultTolerantStepFactoryBeanTests {
// skipped 2,3,4,5
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
// reader exceptions should not cause rollback, 1 writer exception
// causes 2 rollbacks
@@ -480,10 +477,10 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipOnWriteNotDoubleCounted() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7"), Arrays
reader = new SkipReaderStub<String>(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7"), Arrays
.asList(StringUtils.commaDelimitedListToStringArray("2,3")));
writer = new SkipWriterStub(Arrays.asList(StringUtils.commaDelimitedListToStringArray("4,5")));
writer = new SkipWriterStub<String>("4", "5");
factory.setSkipLimit(4);
factory.setItemReader(reader);
@@ -499,7 +496,7 @@ public class FaultTolerantStepFactoryBeanTests {
// skipped 2,3,4,5
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6,7"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
.getName()));
}
@@ -537,8 +534,9 @@ public class FaultTolerantStepFactoryBeanTests {
@Test
public void testSkipOverLimitOnReadWithAllSkipsAtEnd() throws Exception {
reader = new SkipReaderStub(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"),
Arrays.asList(StringUtils.commaDelimitedListToStringArray("6,12,13,14,15")));
reader = new SkipReaderStub<String>(StringUtils
.commaDelimitedListToStringArray("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"), Arrays.asList(StringUtils
.commaDelimitedListToStringArray("6,12,13,14,15")));
factory.setCommitInterval(5);
factory.setSkipLimit(3);
@@ -554,12 +552,12 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals("bad write skip count", 1, stepExecution.getWriteSkipCount());
// writer did not skip "6" as it never made it to writer, only "4" did
assertFalse(reader.processed.contains("6"));
assertTrue(reader.processed.contains("4"));
assertFalse(reader.getRead().contains("6"));
assertTrue(reader.getRead().contains("4"));
// only "1" was ever committed
List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5,7,8,9,10,11"));
assertEquals(expectedOutput, writer.written);
assertEquals(expectedOutput, writer.getCommitted());
assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step
.getName()));
}
@@ -572,7 +570,7 @@ public class FaultTolerantStepFactoryBeanTests {
return item;
}
});
factory.setItemReader(new SkipReaderStub(new String[] { "1", "2", "3", "4" }, NO_FAILURES));
factory.setItemReader(new SkipReaderStub<String>(new String[] { "1", "2", "3", "4" }));
Step step = (Step) factory.getObject();
step.execute(stepExecution);
@@ -795,29 +793,6 @@ public class FaultTolerantStepFactoryBeanTests {
assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus());
}
private static class SkipProcessorStub implements ItemProcessor<String, String> {
private final Collection<String> failures;
private boolean runtimeException = false;
public SkipProcessorStub(Collection<String> failures) {
this.failures = failures;
}
public String process(String item) throws Exception {
if (failures.contains(item)) {
if (runtimeException) {
throw new SkippableRuntimeException("should cause rollback");
}
else {
throw new SkippableException("shouldn't cause rollback");
}
}
return item;
}
}
private static class FilterProcessorStub implements ItemProcessor<String, String> {
private final Collection<String> failures;
@@ -834,48 +809,6 @@ public class FaultTolerantStepFactoryBeanTests {
}
/**
* Simple item reader that supports skip functionality.
*/
private static class SkipReaderStub implements ItemReader<String> {
protected final Log logger = LogFactory.getLog(getClass());
private final String[] items;
private Collection<String> processed = new ArrayList<String>();
private int counter = -1;
private final Collection<String> failures;
public SkipReaderStub() {
this(new String[] { "1", "2", "3", "4", "5" }, Collections.singleton("2"));
}
public SkipReaderStub(String[] items, Collection<String> failures) {
this.items = items;
this.failures = failures;
}
public String read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
logger.debug("Returning null at count=" + counter);
return null;
}
String item = items[counter];
if (failures.contains(item)) {
logger.debug("Throwing exception for [" + item + "] at count=" + counter);
throw new SkippableException("exception in reader");
}
processed.add(item);
logger.debug("Returning [" + item + "] at count=" + counter);
return item;
}
}
private static class ItemProcessListenerStub<T, S> implements ItemProcessListener<T, S> {
private boolean errorEncountered = false;
@@ -905,53 +838,6 @@ public class FaultTolerantStepFactoryBeanTests {
}
}
/**
* Simple item writer that supports skip functionality.
*/
private static class SkipWriterStub implements ItemWriter<String> {
protected final Log logger = LogFactory.getLog(getClass());
// simulate transactional output
private List<Object> written = TransactionAwareProxyFactory.createTransactionalList();
private final Collection<String> failures;
public SkipWriterStub() {
this(Arrays.asList("4"));
}
/**
* @param failures commaDelimitedListToSet
*/
public SkipWriterStub(Collection<String> failures) {
this.failures = failures;
}
public void write(List<? extends String> items) throws Exception {
for (String item : items) {
if (failures.contains(item)) {
logger.debug("Throwing write exception on [" + item + "]");
throw new SkippableRuntimeException("exception in writer");
}
written.add(item);
}
}
}
private static class SkippableException extends Exception {
public SkippableException(String message) {
super(message);
}
}
private static class SkippableRuntimeException extends RuntimeException {
public SkippableRuntimeException(String message) {
super(message);
}
}
private static class FatalRuntimeException extends SkippableRuntimeException {
public FatalRuntimeException(String message) {
super(message);

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class SkipProcessorStub<T> extends ExceptionThrowingItemHandlerStub<T> implements ItemProcessor<T, T> {
private List<T> processed = new ArrayList<T>();
private List<T> committed = TransactionAwareProxyFactory.createTransactionalList();
public SkipProcessorStub() {
super();
}
public SkipProcessorStub(T... failures) {
super(Arrays.asList(failures));
}
public SkipProcessorStub(boolean runtimeException, T... failures) {
this(failures);
this.setRuntimeException(runtimeException);
}
public List<T> getProcessed() {
return processed;
}
public List<T> getCommitted() {
return committed;
}
public void clear() {
processed = new ArrayList<T>();
committed = TransactionAwareProxyFactory.createTransactionalList();
this.setFailures(new ArrayList<T>());
}
public T process(T item) throws Exception {
processed.add(item);
committed.add(item);
checkFailure(item);
return item;
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class SkipReaderStub<T> extends ExceptionThrowingItemHandlerStub<T> implements ItemReader<T> {
private final T[] items;
private List<T> read = new ArrayList<T>();
private int counter = -1;
public SkipReaderStub(T... items) {
super();
this.items = items;
}
public SkipReaderStub(T[] items, Collection<T> failures) {
super(failures);
this.items = items;
}
public SkipReaderStub(T[] items, Collection<T> failures, boolean runtimeException) {
this(items, failures);
this.setRuntimeException(runtimeException);
}
public List<T> getRead() {
return read;
}
public void clear() {
read = new ArrayList<T>();
this.setFailures(new ArrayList<T>());
}
public T read() throws Exception, UnexpectedInputException, ParseException {
counter++;
if (counter >= items.length) {
return null;
}
T item = items[counter];
checkFailure(item);
read.add(item);
return item;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.support.transaction.TransactionAwareProxyFactory;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class SkipWriterStub<T> extends ExceptionThrowingItemHandlerStub<T> implements ItemWriter<T> {
private List<T> written = new ArrayList<T>();
private List<T> committed = TransactionAwareProxyFactory.createTransactionalList();
public SkipWriterStub() {
super();
}
public SkipWriterStub(T... failures) {
super(Arrays.asList(failures));
}
public SkipWriterStub(boolean runtimeException, T... failures) {
this(failures);
this.setRuntimeException(runtimeException);
}
public List<T> getWritten() {
return written;
}
public List<T> getCommitted() {
return committed;
}
public void clear() {
written = new ArrayList<T>();
committed = TransactionAwareProxyFactory.createTransactionalList();
this.setFailures(new ArrayList<T>());
}
public void write(List<? extends T> items) throws Exception {
for (T item : items) {
written.add(item);
committed.add(item);
checkFailure(item);
}
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class SkippableException extends Exception {
public SkippableException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.step.item;
/**
* @author Dan Garrette
* @since 2.0.1
*/
public class SkippableRuntimeException extends RuntimeException {
public SkippableRuntimeException(String message) {
super(message);
}
}