From 6becaa5939c68b9f0443fddd5f12e3a67c63c241 Mon Sep 17 00:00:00 2001 From: robokaso Date: Wed, 26 Mar 2008 12:38:39 +0000 Subject: [PATCH] RESOLVED - issue BATCH-515: RepeatTemplate should unwrap RepeatExceptions also for interceptors (not only for exception handler) http://jira.springframework.org/browse/BATCH-515 --- .../batch/repeat/support/RepeatTemplate.java | 8 +- .../support/SimpleRepeatTemplateTests.java | 73 +++++++++++++++++-- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java index ec9737fb4..e17c0c8e4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java @@ -217,19 +217,19 @@ public class RepeatTemplate implements RepeatOperations { // An exception alone is not sufficient grounds for not // continuing - + Throwable unwrappedThrowable = unwrapIfRethrown(throwable); try { for (int i = listeners.length; i-- > 0;) { RepeatListener interceptor = listeners[i]; - interceptor.onError(context, throwable); + interceptor.onError(context, unwrappedThrowable); // This is not an error - only log at debug // level. logger.debug("Exception intercepted (" + (i + 1) + " of " + listeners.length + ")", - throwable); + unwrappedThrowable); } - exceptionHandler.handleException(context, unwrapIfRethrown(throwable)); + exceptionHandler.handleException(context, unwrappedThrowable); } catch (Throwable handled) { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java index 5a99f02ae..b9ec5e561 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java @@ -22,10 +22,13 @@ import java.util.List; import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatCallback; import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.RepeatException; +import org.springframework.batch.repeat.RepeatListener; import org.springframework.batch.repeat.callback.ItemReaderRepeatCallback; import org.springframework.batch.repeat.callback.NestedRepeatCallback; import org.springframework.batch.repeat.context.RepeatContextSupport; import org.springframework.batch.repeat.exception.ExceptionHandler; +import org.springframework.batch.repeat.listener.RepeatListenerSupport; import org.springframework.batch.repeat.policy.CompletionPolicySupport; import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; @@ -386,20 +389,74 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { assertFalse(result.isContinuable()); } - - public void testCustomExitCode(){ - - ExitStatus status = template.iterate(new RepeatCallback(){ - public ExitStatus doInIteration(RepeatContext context) - throws Exception { + public void testCustomExitCode() { + + ExitStatus status = template.iterate(new RepeatCallback() { + + public ExitStatus doInIteration(RepeatContext context) throws Exception { ExitStatus exitStatus = new ExitStatus(false, "CUSTOM_CODE"); return exitStatus; } - + }); - + assertEquals("CUSTOM_CODE", status.getExitCode()); } + /** + * Checked exceptions are wrapped into runtime RepeatException. + * RepeatException should be unwrapped before before it is passed to + * listeners and exception handler. + */ + public void testExceptionUnwrapping() { + + class TestException extends Exception { + TestException(String msg) { + super(msg); + } + } + final TestException exception = new TestException("CRASH!"); + + class ExceptionHandlerStub implements ExceptionHandler { + boolean called = false; + + public void handleException(RepeatContext context, Throwable throwable) throws Throwable { + called = true; + assertSame(exception, throwable); + throw throwable; // re-throw so that repeat template + // terminates iteration + } + } + ExceptionHandlerStub exHandler = new ExceptionHandlerStub(); + + class RepeatListenerStub extends RepeatListenerSupport { + boolean called = false; + + public void onError(RepeatContext context, Throwable throwable) { + called = true; + assertSame(exception, throwable); + } + } + RepeatListenerStub listener = new RepeatListenerStub(); + + template.setExceptionHandler(exHandler); + template.setListeners(new RepeatListener[] { listener }); + + try { + template.iterate(new RepeatCallback() { + public ExitStatus doInIteration(RepeatContext context) throws Exception { + throw new RepeatException("typically thrown by nested repeat template", exception); + } + }); + fail(); + } + catch (RepeatException expected) { + assertSame(exception, expected.getCause()); + } + + assertTrue(listener.called); + assertTrue(exHandler.called); + + } }