BATCH-220: Rationalise the exception classifiers so they can be used in a retry

This commit is contained in:
dsyer
2008-08-29 14:09:11 +00:00
parent f25fbb5c15
commit 2ea0fe68cf
41 changed files with 925 additions and 781 deletions

View File

@@ -19,7 +19,7 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
@@ -74,11 +74,8 @@ public class CompositeItemProcessListenerTests {
@Test
public void testSetListeners() throws Exception {
compositeListener.setListeners(new ArrayList<ItemProcessListener<? super Object, ? super Object>>() {
{
add(listener);
}
});
compositeListener.setListeners(Collections
.<ItemProcessListener<? super Object, ? super Object>> singletonList(listener));
listener.beforeProcess(null);
replay(listener);
compositeListener.beforeProcess(null);

View File

@@ -1,8 +1,9 @@
package org.springframework.batch.core.repository.dao;
import java.util.HashMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
import java.util.Collections;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
@@ -17,32 +18,30 @@ import org.springframework.transaction.annotation.Transactional;
/**
* Tests for {@link ExecutionContextDao} implementations.
*/
public abstract class AbstractExecutionContextDaoTests extends AbstractTransactionalJUnit4SpringContextTests{
public abstract class AbstractExecutionContextDaoTests extends AbstractTransactionalJUnit4SpringContextTests {
private ExecutionContextDao dao;
private JobExecution jobExecution = new JobExecution(new JobInstance(1L, new JobParameters(), "jobName"), 1L);
private StepExecution stepExecution = new StepExecution("stepName", jobExecution, 1L);
@Before
public void setUp() {
dao = getExecutionContextDao();
}
/**
* @return Configured {@link ExecutionContextDao} implementation ready for use.
* @return Configured {@link ExecutionContextDao} implementation ready for
* use.
*/
protected abstract ExecutionContextDao getExecutionContextDao();
@Transactional @Test
@Transactional
@Test
public void testSaveAndFindContext() {
ExecutionContext ctx = new ExecutionContext(new HashMap<String, Object>() {
{
put("key", "value");
}
});
ExecutionContext ctx = new ExecutionContext(Collections.<String, Object> singletonMap("key", "value"));
jobExecution.setExecutionContext(ctx);
dao.persistExecutionContext(jobExecution);
@@ -50,9 +49,10 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti
assertEquals(ctx, retrieved);
}
@Transactional @Test
@Transactional
@Test
public void testSaveAndFindEmptyContext() {
ExecutionContext ctx = new ExecutionContext();
jobExecution.setExecutionContext(ctx);
dao.persistExecutionContext(jobExecution);
@@ -61,14 +61,12 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti
assertEquals(ctx, retrieved);
}
@Transactional @Test
@Transactional
@Test
public void testUpdateContext() {
ExecutionContext ctx = new ExecutionContext(new HashMap<String, Object>() {
{
put("key", "value");
}
});
ExecutionContext ctx = new ExecutionContext(Collections
.<String, Object> singletonMap("key", "value"));
jobExecution.setExecutionContext(ctx);
dao.persistExecutionContext(jobExecution);
@@ -79,25 +77,23 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti
assertEquals(ctx, retrieved);
assertEquals(7, retrieved.getLong("longKey"));
}
@Transactional @Test
@Transactional
@Test
public void testSaveAndFindStepContext() {
ExecutionContext ctx = new ExecutionContext(new HashMap<String, Object>() {
{
put("key", "value");
}
});
ExecutionContext ctx = new ExecutionContext(Collections.<String, Object> singletonMap("key", "value"));
stepExecution.setExecutionContext(ctx);
dao.persistExecutionContext(stepExecution);
ExecutionContext retrieved = dao.getExecutionContext(stepExecution);
assertEquals(ctx, retrieved);
}
@Transactional @Test
@Transactional
@Test
public void testSaveAndFindEmptyStepContext() {
ExecutionContext ctx = new ExecutionContext();
stepExecution.setExecutionContext(ctx);
dao.persistExecutionContext(stepExecution);
@@ -106,14 +102,11 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti
assertEquals(ctx, retrieved);
}
@Transactional @Test
@Transactional
@Test
public void testUpdateStepContext() {
ExecutionContext ctx = new ExecutionContext(new HashMap<String, Object>() {
{
put("key", "value");
}
});
ExecutionContext ctx = new ExecutionContext(Collections.<String, Object> singletonMap("key", "value"));
stepExecution.setExecutionContext(ctx);
dao.persistExecutionContext(stepExecution);
@@ -124,10 +117,11 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti
assertEquals(ctx, retrieved);
assertEquals(7, retrieved.getLong("longKey"));
}
@Transactional @Test
public void testStoreInteger(){
@Transactional
@Test
public void testStoreInteger() {
ExecutionContext ec = new ExecutionContext();
ec.put("intValue", new Integer(343232));
stepExecution.setExecutionContext(ec);

View File

@@ -16,7 +16,7 @@
package org.springframework.batch.core.step.item;
import java.util.Collection;
import java.util.HashSet;
import java.util.Collections;
import junit.framework.TestCase;
@@ -57,20 +57,15 @@ public class SimpleRetryExceptionHandlerTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)}
* .
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} .
*/
public void testRethrowWhenRetryExhausted() throws Throwable {
RetryPolicy retryPolicy = new NeverRetryPolicy();
RuntimeException ex = new RuntimeException("foo");
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex,
new HashSet<Class<? extends Throwable>>() {
{
add(Error.class);
}
});
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections
.<Class<? extends Throwable>> singleton(Error.class));
// Then pretend to handle the exception in the parent context...
try {
@@ -89,20 +84,15 @@ public class SimpleRetryExceptionHandlerTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)}
* .
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} .
*/
public void testNoRethrowWhenRetryNotExhausted() throws Throwable {
RetryPolicy retryPolicy = new AlwaysRetryPolicy();
RuntimeException ex = new RuntimeException("foo");
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex,
new HashSet<Class<? extends Throwable>>() {
{
add(Error.class);
}
});
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections
.<Class<? extends Throwable>> singleton(Error.class));
// Then pretend to handle the exception in the parent context...
handler.handleException(context.getParent(), ex);
@@ -113,20 +103,15 @@ public class SimpleRetryExceptionHandlerTests extends TestCase {
/**
* Test method for
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)}
* .
* {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} .
*/
public void testRethrowWhenFatal() throws Throwable {
RetryPolicy retryPolicy = new AlwaysRetryPolicy();
RuntimeException ex = new RuntimeException("foo");
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex,
new HashSet<Class<? extends Throwable>>() {
{
add(RuntimeException.class);
}
});
SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections
.<Class<? extends Throwable>> singleton(RuntimeException.class));
// Then pretend to handle the exception in the parent context...
try {

View File

@@ -108,7 +108,7 @@ public class SimpleStepFactoryBeanTests {
public void testSimpleConcurrentJob() throws Exception {
job.setSteps(new ArrayList<Step>());
SimpleStepFactoryBean<String,String> factory = getStepFactory("foo", "bar");
SimpleStepFactoryBean<String, String> factory = getStepFactory("foo", "bar");
factory.setTaskExecutor(new SimpleAsyncTaskExecutor());
factory.setThrottleLimit(1);
@@ -127,14 +127,14 @@ public class SimpleStepFactoryBeanTests {
@Test
public void testSimpleJobWithItemListeners() throws Exception {
SimpleStepFactoryBean<String,String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
SimpleStepFactoryBean<String, String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
factory.setItemWriter(new ItemWriter<String>() {
public void write(List<? extends String> data) throws Exception {
throw new RuntimeException("Error!");
}
});
factory.setListeners(new StepListener[] { new ItemListenerSupport<String,String>() {
factory.setListeners(new StepListener[] { new ItemListenerSupport<String, String>() {
@Override
public void onReadError(Exception ex) {
listened.add(ex);
@@ -154,7 +154,8 @@ public class SimpleStepFactoryBeanTests {
try {
job.execute(jobExecution);
fail("Expected RuntimeException");
} catch (RuntimeException e) {
}
catch (RuntimeException e) {
// expected
assertEquals("Error!", e.getMessage());
}
@@ -168,7 +169,7 @@ public class SimpleStepFactoryBeanTests {
@Test
public void testExceptionTerminates() throws Exception {
SimpleStepFactoryBean<String,String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
SimpleStepFactoryBean<String, String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
factory.setBeanName("exceptionStep");
factory.setItemWriter(new ItemWriter<String>() {
public void write(List<? extends String> data) throws Exception {
@@ -192,9 +193,11 @@ public class SimpleStepFactoryBeanTests {
@Test
public void testExceptionHandler() throws Exception {
SimpleStepFactoryBean<String,String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
SimpleStepFactoryBean<String, String> factory = getStepFactory(new String[] { "foo", "bar", "spam" });
factory.setBeanName("exceptionStep");
factory.setExceptionHandler(new SimpleLimitExceptionHandler(1));
SimpleLimitExceptionHandler exceptionHandler = new SimpleLimitExceptionHandler(1);
exceptionHandler.afterPropertiesSet();
factory.setExceptionHandler(exceptionHandler);
factory.setItemWriter(new ItemWriter<String>() {
int count = 0;
@@ -208,9 +211,9 @@ public class SimpleStepFactoryBeanTests {
job.setSteps(Collections.singletonList((Step) step));
JobExecution jobExecution = repository.createJobExecution(job, new JobParameters());
job.execute(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}
@@ -219,7 +222,7 @@ public class SimpleStepFactoryBeanTests {
String[] items = new String[] { "1", "2", "3", "4", "5", "6", "7" };
int commitInterval = 3;
SimpleStepFactoryBean<String,String> factory = getStepFactory(items);
SimpleStepFactoryBean<String, String> factory = getStepFactory(items);
class CountingChunkListener implements ChunkListener {
int beforeCount = 0;
@@ -259,7 +262,7 @@ public class SimpleStepFactoryBeanTests {
*/
@Test
public void testCommitIntervalMustBeGreaterThanZero() throws Exception {
SimpleStepFactoryBean<String,String> factory = getStepFactory("foo");
SimpleStepFactoryBean<String, String> factory = getStepFactory("foo");
// nothing wrong here
factory.getObject();
@@ -281,7 +284,7 @@ public class SimpleStepFactoryBeanTests {
*/
@Test
public void testCommitIntervalAndCompletionPolicyBothSet() throws Exception {
SimpleStepFactoryBean<String,String> factory = getStepFactory("foo");
SimpleStepFactoryBean<String, String> factory = getStepFactory("foo");
// but exception expected after setting commit interval and completion
// policy
@@ -296,9 +299,9 @@ public class SimpleStepFactoryBeanTests {
}
}
private SimpleStepFactoryBean<String,String> getStepFactory(String... args) throws Exception {
SimpleStepFactoryBean<String,String> factory = new SimpleStepFactoryBean<String,String>();
private SimpleStepFactoryBean<String, String> getStepFactory(String... args) throws Exception {
SimpleStepFactoryBean<String, String> factory = new SimpleStepFactoryBean<String, String>();
List<String> items = new ArrayList<String>();
items.addAll(Arrays.asList(args));
@@ -311,5 +314,5 @@ public class SimpleStepFactoryBeanTests {
factory.setBeanName("stepName");
return factory;
}
}

View File

@@ -46,12 +46,9 @@ public class SkipLimitStepFactoryBeanTests {
private SkipLimitStepFactoryBean<String, String> factory = new SkipLimitStepFactoryBean<String, String>();
private Collection<Class<? extends Throwable>> skippableExceptions = new HashSet<Class<? extends Throwable>>() {
{
add(SkippableException.class);
add(SkippableRuntimeException.class);
}
};
@SuppressWarnings("unchecked")
private Collection<Class<? extends Throwable>> skippableExceptions = new HashSet<Class<? extends Throwable>>(Arrays
.<Class<? extends Throwable>> asList(SkippableException.class, SkippableRuntimeException.class));
private SkipReaderStub reader = new SkipReaderStub();
@@ -139,11 +136,8 @@ public class SkipLimitStepFactoryBeanTests {
*/
@Test
public void testFatalException() throws Exception {
factory.setFatalExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(FatalRuntimeException.class);
}
});
factory.setFatalExceptionClasses(Collections
.<Class<? extends Throwable>> singleton(FatalRuntimeException.class));
factory.setItemWriter(new SkipWriterStub() {
public void write(List<? extends String> items) {
throw new FatalRuntimeException("Ouch!");
@@ -204,11 +198,7 @@ public class SkipLimitStepFactoryBeanTests {
factory.setSkipLimit(3);
factory.setItemReader(reader);
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(Exception.class);
}
});
factory.setSkippableExceptionClasses(Collections.<Class<? extends Throwable>> singleton(Exception.class));
Step step = (Step) factory.getObject();
@@ -246,17 +236,13 @@ public class SkipLimitStepFactoryBeanTests {
factory.setSkipLimit(3);
factory.setItemReader(reader);
factory.setListeners(new StepListener[] { new SkipListenerSupport<String,String>() {
factory.setListeners(new StepListener[] { new SkipListenerSupport<String, String>() {
@Override
public void onSkipInRead(Throwable t) {
throw new RuntimeException("oops");
}
} });
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(Exception.class);
}
});
factory.setSkippableExceptionClasses(Collections.<Class<? extends Throwable>> singleton(Exception.class));
Step step = (Step) factory.getObject();
@@ -287,17 +273,13 @@ public class SkipLimitStepFactoryBeanTests {
factory.setSkipLimit(3);
factory.setItemReader(reader);
factory.setListeners(new StepListener[] { new SkipListenerSupport<String,String>() {
factory.setListeners(new StepListener[] { new SkipListenerSupport<String, String>() {
@Override
public void onSkipInWrite(String item, Throwable t) {
throw new RuntimeException("oops");
}
} });
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(Exception.class);
}
});
factory.setSkippableExceptionClasses(Collections.<Class<? extends Throwable>> singleton(Exception.class));
Step step = (Step) factory.getObject();
@@ -377,11 +359,7 @@ public class SkipLimitStepFactoryBeanTests {
@Test
public void testDefaultSkipPolicy() throws Exception {
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(Exception.class);
}
});
factory.setSkippableExceptionClasses(Collections.<Class<? extends Throwable>> singleton(Exception.class));
factory.setSkipLimit(1);
List<String> items = Arrays.asList(new String[] { "a", "b", "c" });
ItemReader<String> provider = new ListItemReader<String>(items) {
@@ -411,17 +389,13 @@ public class SkipLimitStepFactoryBeanTests {
@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(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);
factory.setItemReader(reader);
factory.setSkippableExceptionClasses(new HashSet<Class<? extends Throwable>>() {
{
add(Exception.class);
}
});
factory.setSkippableExceptionClasses(Collections.<Class<? extends Throwable>> singleton(Exception.class));
Step step = (Step) factory.getObject();

View File

@@ -3,6 +3,7 @@ package org.springframework.batch.core.step.tasklet;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -16,36 +17,38 @@ import org.springframework.batch.repeat.ExitStatus;
public class ConfigurableSystemProcessExitCodeMapperTests {
private ConfigurableSystemProcessExitCodeMapper mapper = new ConfigurableSystemProcessExitCodeMapper();
/**
* Regular usage scenario - mapping adheres to injected values
*/
@Test
public void testMapping() {
Map<Object, ExitStatus> mappings = new HashMap<Object, ExitStatus>() {{
put(0, ExitStatus.FINISHED);
put(1, ExitStatus.FAILED);
put(2, ExitStatus.CONTINUABLE);
put(3, ExitStatus.NOOP);
put(4, ExitStatus.UNKNOWN);
put(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.UNKNOWN);
}};
Map<Object, ExitStatus> mappings = new HashMap<Object, ExitStatus>() {
{
put(0, ExitStatus.FINISHED);
put(1, ExitStatus.FAILED);
put(2, ExitStatus.CONTINUABLE);
put(3, ExitStatus.NOOP);
put(4, ExitStatus.UNKNOWN);
put(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.UNKNOWN);
}
};
mapper.setMappings(mappings);
//check explicitly defined values
// check explicitly defined values
for (Map.Entry<Object, ExitStatus> entry : mappings.entrySet()) {
if (entry.getKey().equals(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY)) continue;
if (entry.getKey().equals(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY))
continue;
int exitCode = (Integer) entry.getKey();
assertSame(entry.getValue(), mapper.getExitStatus(exitCode));
}
//check the else clause
assertSame(mappings.get(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY),
mapper.getExitStatus(5));
// check the else clause
assertSame(mappings.get(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY), mapper.getExitStatus(5));
}
/**
* Else clause is required in the injected map - setter checks its presence.
*/
@@ -59,12 +62,10 @@ public class ConfigurableSystemProcessExitCodeMapperTests {
catch (IllegalArgumentException e) {
// expected
}
Map<Object, ExitStatus> containsElse = new HashMap<Object, ExitStatus>() {{
put(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.FAILED);
}};
Map<Object, ExitStatus> containsElse = Collections.<Object, ExitStatus> singletonMap(
ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.FAILED);
// no error expected now
mapper.setMappings(containsElse);
}
}