diff --git a/spring-batch-core/.settings/org.springframework.ide.eclipse.core.prefs b/spring-batch-core/.settings/org.springframework.ide.eclipse.core.prefs new file mode 100644 index 000000000..d30e2283b --- /dev/null +++ b/spring-batch-core/.settings/org.springframework.ide.eclipse.core.prefs @@ -0,0 +1,67 @@ +#Tue Aug 05 13:02:10 BST 2008 +eclipse.preferences.version=1 +org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true +org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true +org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=true +org.springframework.ide.eclipse.core.enable.project.preferences=false +org.springframework.ide.eclipse.core.validator.enable.com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.ap.quickfix.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.applicationSymbolicNameRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.applicationVersionRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleActivationPolicyRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleActivatorRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleManifestVersionRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleNameRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleSymbolicNameRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.bundleVersionRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.exportPackageRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.importRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.parsingProblemsRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.requireBundleRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.ap.quickfix.importBundleVersionRule-com.springsource.sts.ap.quickfix.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.ap.quickfix.importLibraryVersionRule-com.springsource.sts.ap.quickfix.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.ap.quickfix.importPackageVersionRule-com.springsource.sts.ap.quickfix.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.ap.quickfix.requireBundleVersionRule-com.springsource.sts.ap.quickfix.manifestvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.AvoidDriverManagerDataSource-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ImportElementsAtTopRulee-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ParentBeanSpecifiesAbstractClassRule-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.RefElementRule-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.TooManyBeansInFileRule-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UnnecessaryValueElementRule-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UseBeanInheritance-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java index 8c09068c0..09787e43c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java @@ -89,7 +89,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeStepExecutionListener#afterStep(StepExecution) */ public ExitStatus afterStep(StepExecution stepExecution) { - return stepListener.afterStep(stepExecution); + try { + return stepListener.afterStep(stepExecution); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in afterStep.", e); + } } /** @@ -97,15 +102,26 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeStepExecutionListener#beforeStep(org.springframework.batch.core.StepExecution) */ public void beforeStep(StepExecution stepExecution) { - stepListener.beforeStep(stepExecution); + try { + stepListener.beforeStep(stepExecution); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in beforeStep.", e); + } } /** - * @param e - * @see org.springframework.batch.core.listener.CompositeStepExecutionListener#onErrorInStep(StepExecution, Throwable) + * @param t + * @see org.springframework.batch.core.listener.CompositeStepExecutionListener#onErrorInStep(StepExecution, + * Throwable) */ - public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { - return stepListener.onErrorInStep(stepExecution, e); + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable t) { + try { + return stepListener.onErrorInStep(stepExecution, t); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in onErrorInStep.", t, e); + } } /** @@ -113,7 +129,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeChunkListener#afterChunk() */ public void afterChunk() { - chunkListener.afterChunk(); + try { + chunkListener.afterChunk(); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in afterChunk.", e); + } } /** @@ -121,7 +142,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeChunkListener#beforeChunk() */ public void beforeChunk() { - chunkListener.beforeChunk(); + try { + chunkListener.beforeChunk(); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in beforeChunk.", e); + } } /** @@ -129,7 +155,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeItemReadListener#afterRead(java.lang.Object) */ public void afterRead(Object item) { - itemReadListener.afterRead(item); + try { + itemReadListener.afterRead(item); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in afterRead.", e); + } } /** @@ -137,7 +168,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeItemReadListener#beforeRead() */ public void beforeRead() { - itemReadListener.beforeRead(); + try { + itemReadListener.beforeRead(); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in beforeRead.", e); + } } /** @@ -145,7 +181,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeItemReadListener#onReadError(java.lang.Exception) */ public void onReadError(Exception ex) { - itemReadListener.onReadError(ex); + try { + itemReadListener.onReadError(ex); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in onReadError.", ex, e); + } } /** @@ -153,7 +194,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeItemWriteListener#afterWrite(Object) */ public void afterWrite(Object item) { - itemWriteListener.afterWrite(item); + try { + itemWriteListener.afterWrite(item); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in afterWrite.", e); + } } /** @@ -161,7 +207,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeItemWriteListener#beforeWrite(java.lang.Object) */ public void beforeWrite(Object item) { - itemWriteListener.beforeWrite(item); + try { + itemWriteListener.beforeWrite(item); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in beforeWrite.", e); + } } /** @@ -171,7 +222,12 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * java.lang.Object) */ public void onWriteError(Exception ex, Object item) { - itemWriteListener.onWriteError(ex, item); + try { + itemWriteListener.onWriteError(ex, item); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in onWriteError.", ex, e); + } } /** @@ -179,16 +235,27 @@ public class MulticasterBatchListener implements StepExecutionListener, ChunkLis * @see org.springframework.batch.core.listener.CompositeSkipListener#onSkipInRead(java.lang.Throwable) */ public void onSkipInRead(Throwable t) { - skipListener.onSkipInRead(t); + try { + skipListener.onSkipInRead(t); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in onSkipInRead.", t, e); + } } /** * @param item * @param t - * @see org.springframework.batch.core.listener.CompositeSkipListener#onSkipInWrite(java.lang.Object, java.lang.Throwable) + * @see org.springframework.batch.core.listener.CompositeSkipListener#onSkipInWrite(java.lang.Object, + * java.lang.Throwable) */ public void onSkipInWrite(Object item, Throwable t) { - skipListener.onSkipInWrite(item, t); + try { + skipListener.onSkipInWrite(item, t); + } + catch (RuntimeException e) { + throw new StepListenerFailedException("Error in onSkipInWrite.", t, e); + } } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFailedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFailedException.java new file mode 100644 index 000000000..a5b2ad053 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFailedException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + + +/** + * Exception to indicate a problem in a step listener. + * + * @author Dave Syer + * + */ +public class StepListenerFailedException extends RuntimeException { + + /** + * @param message describes the error to the user + * @param t the exception that was thrown by a listener + */ + public StepListenerFailedException(String message, Throwable t) { + super(message, t); + } + + /** + * @param message describes the error to the user + * @param ex the exception that was thrown by a listener + * @param e the exception that caused the skip + */ + public StepListenerFailedException(String message, Throwable ex, RuntimeException e) { + super(message + "\n" + e.getClass().getName() + ": " + e.getMessage(), ex); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java index da63c6a21..268483980 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipLimitStepFactoryBean.java @@ -191,13 +191,14 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean { if (retryLimit > 0 || skipLimit > 0 || retryPolicy != null) { addFatalExceptionIfMissing(SkipLimitExceededException.class); + addFatalExceptionIfMissing(SkipListenerFailedException.class); addFatalExceptionIfMissing(RetryException.class); if (retryPolicy == null) { SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(retryLimit); if (retryableExceptionClasses.length > 0) { // otherwise we - // retry + // retry // all exceptions simpleRetryPolicy.setRetryableExceptionClasses(retryableExceptionClasses); } @@ -316,8 +317,9 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean { * @param retryTemplate * @param itemKeyGenerator */ - public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate, - ItemKeyGenerator itemKeyGenerator, ItemSkipPolicy readSkipPolicy, ItemSkipPolicy writeSkipPolicy) { + public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, + RetryOperations retryTemplate, ItemKeyGenerator itemKeyGenerator, ItemSkipPolicy readSkipPolicy, + ItemSkipPolicy writeSkipPolicy) { super(itemReader, itemWriter); this.retryOperations = retryTemplate; this.itemKeyGenerator = itemKeyGenerator; @@ -367,7 +369,12 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean { if (readSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) { // increment skip count and try again contribution.incrementTemporaryReadSkipCount(); - listener.onSkipInRead(e); + try { + listener.onSkipInRead(e); + } + catch (RuntimeException ex) { + throw new SkipListenerFailedException("Fatal exception in SkipListener.", ex, e); + } logger.debug("Skipping failed input", e); } else { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipListenerFailedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipListenerFailedException.java new file mode 100644 index 000000000..0a9b7fe12 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipListenerFailedException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import org.springframework.batch.core.SkipListener; +import org.springframework.batch.core.UnexpectedJobExecutionException; + +/** + * Special exception to indicate a failure in a skip listener. These need + * special treatment in the framework in case a skip sends itself into an + * infinite loop. + * + * @author Dave Syer + * + */ +public class SkipListenerFailedException extends UnexpectedJobExecutionException { + + /** + * @param message describes the error to the user + * @param ex the exception that was thrown by a {@link SkipListener} + * @param e the exception that caused the skip + */ + public SkipListenerFailedException(String message, RuntimeException ex, Exception e) { + super(message + "\n" + e.getClass().getName() + ": " + e.getMessage(), ex); + } + +}