RESOLVED - issue BATCH-537: Bad ItemKeyGenerator strategy can lead to infinite loop in retry
Some changes to account for retry exceptions and force a failure if strange hashCode/equals are detected.
This commit is contained in:
@@ -22,6 +22,7 @@ import org.springframework.batch.retry.RetryCallback;
|
||||
import org.springframework.batch.retry.RetryContext;
|
||||
import org.springframework.batch.retry.RetryPolicy;
|
||||
import org.springframework.batch.retry.listener.RetryListenerSupport;
|
||||
import org.springframework.batch.support.BinaryExceptionClassifier;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -34,17 +35,22 @@ public class SimpleRetryExceptionHandler extends RetryListenerSupport implements
|
||||
*/
|
||||
private static final String EXHAUSTED = SimpleRetryExceptionHandler.class.getName() + ".RETRY_EXHAUSTED";
|
||||
|
||||
private RetryPolicy retryPolicy;
|
||||
final private RetryPolicy retryPolicy;
|
||||
|
||||
private ExceptionHandler exceptionHandler;
|
||||
final private ExceptionHandler exceptionHandler;
|
||||
|
||||
final private BinaryExceptionClassifier fatalExceptionClassifier;
|
||||
|
||||
/**
|
||||
* @param retryPolicy
|
||||
* @param exceptionHandler
|
||||
* @param classes
|
||||
*/
|
||||
public SimpleRetryExceptionHandler(RetryPolicy retryPolicy, ExceptionHandler exceptionHandler) {
|
||||
public SimpleRetryExceptionHandler(RetryPolicy retryPolicy, ExceptionHandler exceptionHandler, Class[] classes) {
|
||||
this.retryPolicy = retryPolicy;
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
this.fatalExceptionClassifier = new BinaryExceptionClassifier();
|
||||
fatalExceptionClassifier.setExceptionClasses(classes);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -55,7 +61,7 @@ public class SimpleRetryExceptionHandler extends RetryListenerSupport implements
|
||||
public void handleException(RepeatContext context, Throwable throwable) throws Throwable {
|
||||
// Only bother to check the delegate exception handler if we know that
|
||||
// retry is exhausted
|
||||
if (context.hasAttribute(EXHAUSTED)) {
|
||||
if (!fatalExceptionClassifier.isDefault(throwable) || context.hasAttribute(EXHAUSTED)) {
|
||||
exceptionHandler.handleException(context, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +111,8 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean {
|
||||
* to absorb exceptions at the step level because the failed items
|
||||
* will never re-appear after a rollback.
|
||||
*/
|
||||
List fatalExceptionList = new ArrayList(Arrays.asList(fatalExceptionClasses));
|
||||
if (!fatalExceptionList.contains(SkipLimitExceededException.class)) {
|
||||
fatalExceptionList.add(SkipLimitExceededException.class);
|
||||
}
|
||||
fatalExceptionClasses = (Class[]) fatalExceptionList.toArray(new Class[0]);
|
||||
addFatalExceptionIfMissing(SkipLimitExceededException.class);
|
||||
List fatalExceptionList = Arrays.asList(fatalExceptionClasses);
|
||||
|
||||
LimitCheckingItemSkipPolicy skipPolicy = new LimitCheckingItemSkipPolicy(skipLimit, Arrays
|
||||
.asList(skippableExceptionClasses), fatalExceptionList);
|
||||
@@ -143,4 +140,15 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean {
|
||||
step.setItemHandler(itemHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public void addFatalExceptionIfMissing(Class cls) {
|
||||
List fatalExceptionList = new ArrayList(Arrays.asList(fatalExceptionClasses));
|
||||
if (!fatalExceptionList.contains(cls)) {
|
||||
fatalExceptionList.add(cls);
|
||||
}
|
||||
fatalExceptionClasses = (Class[]) fatalExceptionList.toArray(new Class[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.batch.item.ItemKeyGenerator;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemRecoverer;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.retry.RetryException;
|
||||
import org.springframework.batch.retry.RetryListener;
|
||||
import org.springframework.batch.retry.RetryOperations;
|
||||
import org.springframework.batch.retry.RetryPolicy;
|
||||
@@ -116,6 +117,8 @@ public class StatefulRetryStepFactoryBean extends SkipLimitStepFactoryBean {
|
||||
|
||||
if (retryLimit > 0) {
|
||||
|
||||
addFatalExceptionIfMissing(RetryException.class);
|
||||
|
||||
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit);
|
||||
if (retryableExceptionClasses != null) {
|
||||
retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses);
|
||||
@@ -124,7 +127,7 @@ public class StatefulRetryStepFactoryBean extends SkipLimitStepFactoryBean {
|
||||
|
||||
// Co-ordinate the retry policy with the exception handler:
|
||||
getStepOperations()
|
||||
.setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler()));
|
||||
.setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler(), getFatalExceptionClasses()));
|
||||
|
||||
ItemWriterRetryPolicy itemProviderRetryPolicy = new ItemWriterRetryPolicy(retryPolicy);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user