REOPENED - issue BATCH-511: read failures cause rollback

This commit is contained in:
dsyer
2008-03-27 10:30:06 +00:00
parent 419fa9794d
commit e46c972d8e
4 changed files with 125 additions and 33 deletions

View File

@@ -32,6 +32,8 @@ public class StepContribution {
private int skipCount;
private int readSkipCount;
/**
* @param execution
*/
@@ -72,10 +74,11 @@ public class StepContribution {
/**
* @return the sum of skips accumulated in the parent {@link StepExecution}
* and this <code>StepContribution</code>.
* and this <code>StepContribution</code>, including uncommitted read
* skips.
*/
public int getStepSkipCount() {
return skipCount + parentSkipCount;
return readSkipCount + skipCount + parentSkipCount;
}
/**
@@ -88,18 +91,25 @@ public class StepContribution {
}
/**
* Increment the skip count
* Increment the total skip count for this contribution
*/
public void incrementSkipCount() {
skipCount++;
}
/**
* Increment the skip count by a non-trivial amount
* @param delta
* Increment the counter for skipped reads
*/
public void incrementSkipCount(int delta) {
skipCount += delta;
public void incrementReadSkipCount() {
this.readSkipCount++;
}
/**
* Clear the read skips and transfer them to the total skip count
*/
public void commitReadSkipCount() {
skipCount += readSkipCount;
readSkipCount = 0;
}
/*
@@ -107,7 +117,8 @@ public class StepContribution {
* @see java.lang.Object#toString()
*/
public String toString() {
return "[StepContribution: items="+itemCount+", commits=" + commitCount + ", skips=" + skipCount + "]";
return "[StepContribution: items=" + itemCount + ", commits=" + commitCount + ", readSkips=" + readSkipCount
+ ", skips=" + skipCount + "]";
}
}

View File

@@ -299,6 +299,7 @@ public class ItemOrientedStep extends AbstractStep {
Thread.currentThread().interrupt();
}
contribution.commitReadSkipCount();
// Apply the contribution to the step
// only if chunk was successful
stepExecution.apply(contribution);
@@ -330,13 +331,11 @@ public class ItemOrientedStep extends AbstractStep {
}
catch (Error e) {
stepExecution.incrementSkipCountBy(contribution.getSkipCount());
processRollback(stepExecution, fatalException, transaction);
processRollback(stepExecution, contribution, fatalException, transaction);
throw e;
}
catch (Exception e) {
stepExecution.incrementSkipCountBy(contribution.getSkipCount());
processRollback(stepExecution, fatalException, transaction);
processRollback(stepExecution, contribution, fatalException, transaction);
throw e;
}
finally {
@@ -525,11 +524,14 @@ public class ItemOrientedStep extends AbstractStep {
/**
* @param stepExecution
* @param contribution
* @param fatalException
* @param transaction
*/
private void processRollback(final StepExecution stepExecution, final ExceptionHolder fatalException,
private void processRollback(final StepExecution stepExecution, final StepContribution contribution, final ExceptionHolder fatalException,
TransactionStatus transaction) {
stepExecution.incrementSkipCountBy(contribution.getSkipCount());
/*
* Any exception thrown within the transaction should automatically
* cause the transaction to rollback.

View File

@@ -28,6 +28,7 @@ import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.listener.CompositeSkipListener;
import org.springframework.batch.core.step.skip.ItemSkipPolicy;
import org.springframework.batch.core.step.skip.NeverSkipItemSkipPolicy;
import org.springframework.batch.core.step.skip.SkipLimitExceededException;
import org.springframework.batch.item.ItemKeyGenerator;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
@@ -48,9 +49,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
/**
* Key for transaction resource that holds skipped keys until they can be removed
* Key for transaction resource that holds skipped keys until they can be
* removed
*/
private static final String TO_BE_REMOVED = ItemSkipPolicyItemHandler.class.getName()+".TO_BE_REMOVED";
private static final String TO_BE_REMOVED = ItemSkipPolicyItemHandler.class.getName() + ".TO_BE_REMOVED";
protected final Log logger = LogFactory.getLog(getClass());
@@ -153,17 +155,26 @@ public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
}
catch (Exception e) {
if (itemSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) {
// increment skip count and try again
contribution.incrementSkipCount();
if (listener != null) {
listener.onSkipInRead(e);
try {
if (itemSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) {
// increment skip count and try again
contribution.incrementReadSkipCount();
if (listener != null) {
listener.onSkipInRead(e);
}
logger.debug("Skipping failed input", e);
}
else {
// re-throw only when the skip policy runs out of
// patience
throw e;
}
logger.debug("Skipping failed input", e);
}
else {
// re-throw only when the skip policy runs out of patience
throw e;
catch (SkipLimitExceededException ex) {
// we are headed for a abnormal ending so bake in the skip
// count
contribution.commitReadSkipCount();
throw ex;
}
}
@@ -198,7 +209,7 @@ public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
throw e;
}
}
public void mark() throws MarkFailedException {
super.mark();
clearSkippedExceptions();
@@ -235,9 +246,10 @@ public class ItemSkipPolicyItemHandler extends SimpleItemHandler {
return;
}
synchronized (skippedExceptions) {
for (Iterator iterator = ((Set) TransactionSynchronizationManager.getResource(TO_BE_REMOVED)).iterator(); iterator.hasNext();) {
for (Iterator iterator = ((Set) TransactionSynchronizationManager.getResource(TO_BE_REMOVED)).iterator(); iterator
.hasNext();) {
Object key = (Object) iterator.next();
skippedExceptions.remove(key);
skippedExceptions.remove(key);
}
TransactionSynchronizationManager.unbindResource(TO_BE_REMOVED);
}