diff --git a/spring-batch-core/.settings/org.maven.ide.eclipse.prefs b/spring-batch-core/.settings/org.maven.ide.eclipse.prefs index 1c714f57f..c77475b58 100644 --- a/spring-batch-core/.settings/org.maven.ide.eclipse.prefs +++ b/spring-batch-core/.settings/org.maven.ide.eclipse.prefs @@ -1,5 +1,5 @@ -#Tue Jul 07 12:34:28 BST 2009 -activeProfiles=spring3 +#Thu Jul 09 13:28:42 BST 2009 +activeProfiles= eclipse.preferences.version=1 fullBuildGoals=process-test-resources includeModules=false diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index 3545f42b8..5a603c04b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -18,6 +18,7 @@ package org.springframework.batch.core.configuration.xml; import java.util.Collection; +import org.springframework.batch.classify.BinaryExceptionClassifier; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecutionListener; import org.springframework.batch.core.StepListener; @@ -282,7 +283,7 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { } ts.setStepExecutionListeners((StepExecutionListener[]) newListeners); } - if (transactionTimeout != null || propagation != null || isolation != null) { + if (transactionTimeout != null || propagation != null || isolation != null || noRollbackExceptionClasses!=null) { DefaultTransactionAttribute attribute = new DefaultTransactionAttribute(); if (propagation != null) { attribute.setPropagationBehavior(propagation.value()); @@ -293,18 +294,12 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware { if (transactionTimeout != null) { attribute.setTimeout(transactionTimeout); } + final BinaryExceptionClassifier classifier = new BinaryExceptionClassifier(noRollbackExceptionClasses, false); ts.setTransactionAttribute(new DefaultTransactionAttribute(attribute) { - - /** - * Ignore the default behaviour and rollback on all exceptions - * that bubble up to the tasklet level. The tasklet has to deal - * with the rollback rules internally. - */ @Override public boolean rollbackOn(Throwable ex) { - return true; + return classifier.classify(ex); } - }); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java index d53b09dcc..8559fc4c3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java @@ -17,14 +17,13 @@ package org.springframework.batch.core.listener; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.support.PatternMatcher; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; -import com.sun.org.apache.xerces.internal.impl.xpath.XPath.Step; - /** * This class can be used to automatically promote items from the {@link Step} * {@link ExecutionContext} to the {@link Job} {@link ExecutionContext} at the diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java index 8a8fb7075..a0794d38a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java @@ -19,11 +19,10 @@ import java.util.Arrays; import java.util.Collection; import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; import org.springframework.batch.item.ExecutionContext; -import com.sun.org.apache.xerces.internal.impl.xpath.XPath.Step; - /** * This class can be used to automatically copy items from the * {@link JobParameters} to the {@link Step} {@link ExecutionContext}. A list of diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java index eb932568d..b6db2b994 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java @@ -46,6 +46,8 @@ import org.springframework.batch.retry.policy.RetryContextCache; import org.springframework.batch.retry.policy.SimpleRetryPolicy; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; +import org.springframework.transaction.interceptor.DefaultTransactionAttribute; +import org.springframework.transaction.interceptor.TransactionAttribute; /** * Factory bean for step that provides options for configuring skip behaviour. @@ -244,6 +246,25 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean classifier = getRollbackClassifier(); + return new DefaultTransactionAttribute(attribute) { + @Override + public boolean rollbackOn(Throwable ex) { + return classifier.classify(ex); + } + + }; + + } + @Override protected void applyConfiguration(TaskletStep step) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java index 4c25f0100..ed9df6d32 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java @@ -31,6 +31,8 @@ import org.springframework.batch.support.transaction.TransactionAwareProxyFactor * @since 2.0.2 */ public class ExceptionThrowingTaskletStub implements Tasklet { + + private int maxTries = 4; protected Log logger = LogFactory.getLog(getClass()); @@ -56,6 +58,9 @@ public class ExceptionThrowingTaskletStub implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { committed.add(1); + if (committed.size()>=maxTries) { + return RepeatStatus.FINISHED; + } throw exception.newInstance("Expected exception"); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java index 034129f2a..f14495485 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java @@ -50,7 +50,7 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa @Autowired private SkipWriterStub writer; - + @Autowired private ExceptionThrowingTaskletStub tasklet; @@ -59,7 +59,7 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } - + @Before public void setup() { reader.clear(); @@ -89,8 +89,10 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(RuntimeException.class); StepExecution stepExecution = launchStep("skippableStep"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[]", + // writer.getCommitted().toString()); } @Test @@ -116,8 +118,10 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(Exception.class); StepExecution stepExecution = launchStep("skippableStep"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[]", + // writer.getCommitted().toString()); } @Test @@ -144,7 +148,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa StepExecution stepExecution = launchStep("retryable"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[]", + // writer.getCommitted().toString()); } @Test @@ -161,7 +166,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(FatalRuntimeException.class); StepExecution stepExecution = launchStep("retryable"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", + // writer.getWritten().toString()); assertEquals("[]", writer.getCommitted().toString()); } @@ -171,7 +177,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa StepExecution stepExecution = launchStep("retryable"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[]", + // writer.getCommitted().toString()); } @Test @@ -188,7 +195,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(FatalException.class); StepExecution stepExecution = launchStep("retryable"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 1, 2, 3]", + // writer.getWritten().toString()); assertEquals("[]", writer.getCommitted().toString()); } @@ -197,8 +205,10 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(RuntimeException.class); StepExecution stepExecution = launchStep("noRollbackDefault"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[]", + // writer.getCommitted().toString()); } @Test @@ -206,9 +216,12 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(SkippableRuntimeException.class); StepExecution stepExecution = launchStep("noRollbackDefault"); assertNotNull(stepExecution); - // TODO BATCH-1318: assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals(BatchStatus.FAILED, + // stepExecution.getStatus()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getCommitted().toString()); } @Test @@ -226,7 +239,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa StepExecution stepExecution = launchStep("noRollbackSkippable"); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals("[1, 2, 3, 1, 2, 3, 4]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 4]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3, 1, 2, 3, 4]", + // writer.getCommitted().toString()); } @Test @@ -243,13 +257,15 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa writer.setExceptionType(FatalRuntimeException.class); StepExecution stepExecution = launchStep("noRollbackFatal"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getWritten().toString()); - // TODO BATCH-1318: assertEquals("[1, 2, 3]", writer.getCommitted().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getWritten().toString()); + // TODO BATCH-1318: assertEquals("[1, 2, 3]", + // writer.getCommitted().toString()); } @Test public void testNoRollbackTaskletRollbackException() throws Exception { - tasklet.setExceptionType(FatalRuntimeException.class); + tasklet.setExceptionType(RuntimeException.class); StepExecution stepExecution = launchStep("noRollbackTasklet"); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals("[]", tasklet.getCommitted().toString()); @@ -259,8 +275,10 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa public void testNoRollbackTaskletNoRollbackException() throws Exception { tasklet.setExceptionType(SkippableRuntimeException.class); StepExecution stepExecution = launchStep("noRollbackTasklet"); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // TODO BATCH-1298: assertEquals("[1]", tasklet.getCommitted().toString()); + // assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + // BATCH-1298: + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals("[1, 1, 1, 1]", tasklet.getCommitted().toString()); } private StepExecution launchStep(String stepName) throws JobExecutionAlreadyRunningException, JobRestartException, diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/BinaryExceptionClassifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/BinaryExceptionClassifier.java index 3701f5628..e43c9b7c9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/BinaryExceptionClassifier.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/classify/BinaryExceptionClassifier.java @@ -60,7 +60,7 @@ public class BinaryExceptionClassifier extends SubclassClassifier> exceptionClasses, boolean value) { this(!value); - setTypes(exceptionClasses); + if (exceptionClasses!=null) setTypes(exceptionClasses); } /**