RESOLVED - issue BATCH-457: Error handling broken in SimpleJob

Look out for Error types explicitly and re-throw them without wrapping
This commit is contained in:
dsyer
2008-03-14 08:53:27 +00:00
parent 1a316c1aa9
commit 4fd2968e5e
8 changed files with 302 additions and 151 deletions

View File

@@ -22,7 +22,6 @@ import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.ItemSkipPolicy;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
@@ -31,7 +30,7 @@ import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.SimpleJob;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.listener.JobListenerSupport;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
@@ -252,6 +251,21 @@ public class SimpleJobTests extends TestCase {
checkRepository(BatchStatus.FAILED, ExitStatus.FAILED);
}
public void testFailedWithError() throws Exception {
stepConfiguration1.setStartLimit(5);
stepConfiguration2.setStartLimit(5);
final Error exception = new Error("Foo!");
stepConfiguration1.setProcessException(exception);
try {
job.execute(jobExecution);
} catch (Error e) {
assertEquals(exception, e);
}
System.err.println(list);
assertEquals(0, list.size());
checkRepository(BatchStatus.FAILED, ExitStatus.FAILED);
}
public void testStepShouldNotStart() throws Exception {
// Start policy will return false, keeping the step from being started.
stepConfiguration1.setStartLimit(0);
@@ -320,7 +334,7 @@ public class SimpleJobTests extends TestCase {
private class StubStep extends AbstractStep {
private Runnable runnable;
private Exception exception;
private Throwable exception;
protected ExceptionHandler exceptionHandler;
protected RetryPolicy retryPolicy;
protected JobRepository jobRepository;
@@ -339,7 +353,7 @@ public class SimpleJobTests extends TestCase {
/**
* @param exception
*/
public void setProcessException(Exception exception) {
public void setProcessException(Throwable exception) {
this.exception = exception;
}
@@ -355,6 +369,10 @@ public class SimpleJobTests extends TestCase {
stepExecution.setExitStatus(ExitStatus.FAILED);
throw (RuntimeException) exception;
}
if (exception instanceof Error) {
stepExecution.setExitStatus(ExitStatus.FAILED);
throw (Error) exception;
}
if (exception instanceof JobInterruptedException) {
stepExecution.setExitStatus(ExitStatus.FAILED);
throw (JobInterruptedException) exception;

View File

@@ -468,7 +468,7 @@ public class ItemOrientedStepTests extends TestCase {
StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy() {
public void checkInterrupted(RepeatContext context) throws JobInterruptedException {
throw new JobInterruptedException("");
throw new JobInterruptedException("interrupted");
}
};
@@ -499,12 +499,12 @@ public class ItemOrientedStepTests extends TestCase {
try {
itemOrientedStep.execute(stepExecution);
fail("Expected StepInterruptedException");
fail("Expected JobInterruptedException");
} catch (JobInterruptedException ex) {
assertEquals(BatchStatus.STOPPED, stepExecution.getStatus());
String msg = stepExecution.getExitStatus().getExitDescription();
assertTrue("Message does not contain JobInterruptedException: " + msg, contains(msg,
"JobInterruptedException"));
assertTrue("Message does not contain 'interrupted': " + msg, contains(msg,
"interrupted"));
}
}
@@ -534,6 +534,32 @@ public class ItemOrientedStepTests extends TestCase {
}
}
public void testStatusForErrorFailure() throws Exception {
ItemReader itemReader = new AbstractItemReader() {
public Object read() throws Exception {
// Trigger a rollback
throw new Error("Foo");
}
};
itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter));
JobExecution jobExecutionContext = new JobExecution(jobInstance);
StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext);
stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar")));
// step.setLastExecution(stepExecution);
try {
itemOrientedStep.execute(stepExecution);
fail("Expected Error");
} catch (Error ex) {
assertEquals(BatchStatus.FAILED, stepExecution.getStatus());
// The original rollback was caused by this one:
assertEquals("Foo", ex.getMessage());
}
}
public void testStatusForResetFailedException() throws Exception {
ItemReader itemReader = new AbstractItemReader() {

View File

@@ -27,7 +27,7 @@ public class TaskletStepTests extends TestCase {
protected void setUp() throws Exception {
stepExecution = new StepExecution(new StepSupport("stepName"), new JobExecution(new JobInstance(new Long(0L),
new JobParameters(), new JobSupport("testJob")), new Long(12)));
new JobParameters(), new JobSupport("testJob")), new Long(12)));
}
public void testTaskletMandatory() throws Exception {
@@ -35,7 +35,8 @@ public class TaskletStepTests extends TestCase {
step.setJobRepository(new JobRepositorySupport());
try {
step.afterPropertiesSet();
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
String message = e.getMessage();
assertTrue("Message should contain 'tasklet': " + message, contains(message.toLowerCase(), "tasklet"));
}
@@ -45,7 +46,8 @@ public class TaskletStepTests extends TestCase {
TaskletStep step = new TaskletStep();
try {
step.afterPropertiesSet();
} catch (IllegalArgumentException e) {
}
catch (IllegalArgumentException e) {
String message = e.getMessage();
assertTrue("Message should contain 'tasklet': " + message, contains(message.toLowerCase(), "tasklet"));
}
@@ -88,7 +90,8 @@ public class TaskletStepTests extends TestCase {
try {
step.execute(stepExecution);
fail("Expected BatchCriticalException");
} catch (UnexpectedJobExecutionException e) {
}
catch (UnexpectedJobExecutionException e) {
assertEquals("foo", e.getCause().getMessage());
}
assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus());
@@ -123,7 +126,21 @@ public class TaskletStepTests extends TestCase {
try {
step.execute(stepExecution);
fail();
} catch (RuntimeException e) {
}
catch (RuntimeException e) {
assertNotNull(stepExecution.getStartTime());
assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus());
assertNotNull(stepExecution.getEndTime());
}
}
public void testExceptionError() throws JobInterruptedException, UnexpectedJobExecutionException {
TaskletStep step = new TaskletStep(new StubTasklet(new Error("Foo!")), new JobRepositorySupport());
try {
step.execute(stepExecution);
fail();
}
catch (Error e) {
assertNotNull(stepExecution.getStartTime());
assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus());
assertNotNull(stepExecution.getEndTime());
@@ -131,20 +148,22 @@ public class TaskletStepTests extends TestCase {
}
/**
* When job is interrupted the {@link JobInterruptedException} should be propagated up.
* When job is interrupted the {@link JobInterruptedException} should be
* propagated up.
*/
public void testJobInterrupted() throws Exception {
TaskletStep step = new TaskletStep(new Tasklet() {
public ExitStatus execute() throws Exception {
throw new JobInterruptedException("Interrupted while executing tasklet");
throw new JobInterruptedException("Job interrupted while executing tasklet");
}
}, new JobRepositorySupport());
try {
step.execute(stepExecution);
fail();
} catch (JobInterruptedException expected) {
assertEquals("Interrupted while executing tasklet", expected.getMessage());
}
catch (JobInterruptedException expected) {
assertEquals("Job interrupted while executing tasklet", expected.getMessage());
}
}
@@ -158,6 +177,8 @@ public class TaskletStepTests extends TestCase {
private StepExecution stepExecution;
private Throwable exception = null;
public StubTasklet(boolean exitFailure, boolean throwException) {
this(exitFailure, throwException, false);
}
@@ -168,10 +189,24 @@ public class TaskletStepTests extends TestCase {
this.assertStepContext = assertStepContext;
}
/**
* @param b
* @param error
*/
public StubTasklet(Throwable error) {
this(false, false, false);
this.exception = error;
}
public ExitStatus execute() throws Exception {
if (throwException) {
throw new Exception();
}
if (exception!=null) {
if (exception instanceof Exception) throw (Exception) exception;
if (exception instanceof Error) throw (Error) exception;
}
if (exitFailure) {
return ExitStatus.FAILED;