OPEN - issue BATCH-87: Recoverable is a nasty abstraction - encourages stateful Tasklets.

http://opensource.atlassian.com/projects/spring/browse/BATCH-87

Moved recovery responsibility to a separate infrastructure interface.
This commit is contained in:
dsyer
2007-12-16 14:22:34 +00:00
parent a48b7847e3
commit 3c34d95ff8
11 changed files with 187 additions and 53 deletions

View File

@@ -27,6 +27,7 @@ import org.springframework.batch.core.tasklet.Tasklet;
import org.springframework.batch.io.Skippable;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemProvider;
import org.springframework.batch.item.ItemRecoverer;
import org.springframework.batch.repeat.ExitStatus;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.synch.RepeatSynchronizationManager;
@@ -106,6 +107,8 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab
protected ItemProcessor itemProcessor;
private ItemRecoverer itemRecoverer;
/**
* Check mandatory properties (provider and processor), and ensure that only
* one (or neither) of {@link RetryPolicy} or {@link RetryOperations} is
@@ -123,6 +126,9 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab
template.setRetryPolicy(new ItemProviderRetryPolicy(retryPolicy));
retryOperations = template;
}
if (itemRecoverer==null && (itemProvider instanceof ItemRecoverer)) {
itemRecoverer = (ItemRecoverer) itemProvider;
}
}
/**
@@ -166,7 +172,9 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab
try {
Object data = context.getAttribute(ITEM_KEY);
itemProvider.recover(data, cause);
if (itemRecoverer!=null) {
itemRecoverer.recover(data, cause);
}
}
finally {
context.removeAttribute(ITEM_KEY);
@@ -187,6 +195,15 @@ public class ItemProviderProcessTasklet implements Tasklet, Recoverable, Skippab
this.itemProcessor = moduleProcessor;
}
/**
* Setter for injecting optional recovery handler.
*
* @param itemRecoverer
*/
public void setRecoverer(ItemRecoverer itemRecoverer) {
this.itemRecoverer = itemRecoverer;
}
/**
* If the provider and / or processor are {@link Skippable} then delegate to
* them in that order.

View File

@@ -85,15 +85,15 @@ public class SimpleJobTests extends TestCase {
});
}
private Tasklet getTasklet(String arg) {
private Tasklet getTasklet(String arg) throws Exception {
return getTasklet(new String[] { arg });
}
private Tasklet getTasklet(String arg0, String arg1) {
private Tasklet getTasklet(String arg0, String arg1) throws Exception {
return getTasklet(new String[] { arg0, arg1 });
}
private Tasklet getTasklet(String[] args) {
private Tasklet getTasklet(String[] args) throws Exception {
ItemProviderProcessTasklet module = new ItemProviderProcessTasklet();
List items = TransactionAwareProxyFactory.createTransactionalList();
items.addAll(Arrays.asList(args));
@@ -106,6 +106,7 @@ public class SimpleJobTests extends TestCase {
};
module.setItemProvider(provider);
module.setItemProcessor(processor);
module.afterPropertiesSet();
return module;
}

View File

@@ -211,6 +211,8 @@ public class ItemProviderProcessTaskletTests extends TestCase {
}
});
module.afterPropertiesSet();
try {
module.execute();
fail("Expected RuntimeException");