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:
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user