Merging changes from branch...

BATCH-1323: Modify skip/retry/no-rollback exception class configurations to allow for include/exclude
BATCH-1339: Move task-executor attribute up from <chunk/> to <tasklet/>
BATCH-1348: Allow inlining of reader/writer/processor into <chunk/>
BATCH-1357: Allow empty <listeners/>, <retry-listeners/>, and <streams/> lists
BATCH-1358: Move InfiniteLoopIncrementer into core, and rename it to RunIdIncrementer
BATCH-1367: Syntactic sugar for Item*Adapter in namespace
BATCH-1375: Give CompositeItemProcessor's and CompositeItemWriter's property the same name (delegates)
This commit is contained in:
dhgarrette
2009-08-23 15:17:20 +00:00
parent 9e8bdba83d
commit 8146e55503
72 changed files with 1168 additions and 902 deletions

View File

@@ -34,9 +34,7 @@ import java.util.Map;
public class BinaryExceptionClassifier extends SubclassClassifier<Throwable, Boolean> {
/**
* Create a binary exception classifier with the provided default value. All
* exceptions will classify as this value unless
* {@link #setTypes(Collection)} is used to narrow the field.
* Create a binary exception classifier with the provided default value.
*
* @param defaultValue defaults to false
*/
@@ -44,23 +42,22 @@ public class BinaryExceptionClassifier extends SubclassClassifier<Throwable, Boo
super(defaultValue);
}
/**
* Create a binary exception classifier with the default value (false). All
* exceptions will classify as false.
*/
public BinaryExceptionClassifier() {
this(false);
}
/**
* Create a binary exception classifier with the provided classes and their
* subclasses. The mapped value for these exceptions will be the one
* provided (which will be the opposite of the default).
*
* @param value
*/
public BinaryExceptionClassifier(Collection<Class<? extends Throwable>> exceptionClasses, boolean value) {
this(!value);
if (exceptionClasses!=null) setTypes(exceptionClasses);
if (exceptionClasses != null) {
Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>();
for (Class<? extends Throwable> type : exceptionClasses) {
map.put(type, !getDefault());
}
setTypeMap(map);
}
}
/**
@@ -72,17 +69,23 @@ public class BinaryExceptionClassifier extends SubclassClassifier<Throwable, Boo
}
/**
* Set of Throwable class types to keys for the classifier. Any subclass of
* the type provided will be classified as of non-default type.
* Create a binary exception classifier using the given classification map
* and a default classification of false.
*
* @param types the types to classify as non-default
* @param typeMap
*/
public final void setTypes(Collection<Class<? extends Throwable>> types) {
Map<Class<? extends Throwable>, Boolean> map = new HashMap<Class<? extends Throwable>, Boolean>();
for (Class<? extends Throwable> type : types) {
map.put(type, !getDefault());
}
setTypeMap(map);
public BinaryExceptionClassifier(Map<Class<? extends Throwable>, Boolean> typeMap) {
this(typeMap, false);
}
/**
* Create a binary exception classifier using the given classification map
* and a default classification of false.
*
* @param typeMap
*/
public BinaryExceptionClassifier(Map<Class<? extends Throwable>, Boolean> typeMap, boolean defaultValue) {
super(typeMap, defaultValue);
}
}

View File

@@ -25,40 +25,38 @@ import org.springframework.util.Assert;
/**
* Composite {@link ItemProcessor} that passes the item through a sequence of
* injected <code>ItemTransformer</code>s (return value of previous
* transformation is the entry value of the next).<br/><br/>
* transformation is the entry value of the next).<br/>
* <br/>
*
* Note the user is responsible for injecting a chain of {@link ItemProcessor}
* s that conforms to declared input and output types.
* Note the user is responsible for injecting a chain of {@link ItemProcessor} s
* that conforms to declared input and output types.
*
* @author Robert Kasanicky
*/
@SuppressWarnings("unchecked")
public class CompositeItemProcessor<I, O> implements ItemProcessor<I, O>, InitializingBean {
private List<ItemProcessor> itemProcessors;
private List<ItemProcessor<Object, Object>> delegates;
@SuppressWarnings("unchecked")
public O process(I item) throws Exception {
Object result = item;
for(ItemProcessor transformer: itemProcessors){
if(result == null){
for (ItemProcessor<Object, Object> delegate : delegates) {
if (result == null) {
return null;
}
result = transformer.process(result);
result = delegate.process(result);
}
return (O) result;
}
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(itemProcessors);
Assert.notNull(delegates, "The 'delgates' may not be null");
Assert.notEmpty(delegates, "The 'delgates' may not be empty");
}
/**
* @param itemProcessors will be chained to produce a composite
* transformation.
*/
public void setItemProcessors(List<ItemProcessor> itemProcessors) {
this.itemProcessors = itemProcessors;
public void setDelegates(List<ItemProcessor<Object, Object>> delegates) {
this.delegates = delegates;
}
}

View File

@@ -16,34 +16,38 @@
package org.springframework.batch.item.support;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Calls a collection of {@link ItemWriter}s in fixed-order sequence.<br/><br/>
* Calls a collection of {@link ItemWriter}s in fixed-order sequence.<br/>
* <br/>
*
* The implementation is thread-safe if all delegates are thread-safe.
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public class CompositeItemWriter<T> implements ItemWriter<T> {
public class CompositeItemWriter<T> implements ItemWriter<T>, InitializingBean {
private List<ItemWriter<? super T>> delegates;
public void setDelegates(ItemWriter<? super T>[] delegates) {
this.delegates = Arrays.asList(delegates);
}
/**
* Calls injected ItemProcessors in order.
*/
public void write(List<? extends T> item) throws Exception {
public void write(List<? extends T> item) throws Exception {
for (ItemWriter<? super T> writer : delegates) {
writer.write(item);
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(delegates, "The 'delgates' may not be null");
Assert.notEmpty(delegates, "The 'delgates' may not be empty");
}
public void setDelegates(List<ItemWriter<? super T>> delegates) {
this.delegates = delegates;
}
}

View File

@@ -16,8 +16,7 @@
package org.springframework.batch.retry.policy;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import org.springframework.batch.classify.BinaryExceptionClassifier;
import org.springframework.batch.retry.RetryContext;
@@ -43,44 +42,26 @@ import org.springframework.batch.retry.context.RetryContextSupport;
*/
public class SimpleRetryPolicy implements RetryPolicy {
/**
* The default limit to the number of attempts for a new policy.
*/
public final static int DEFAULT_MAX_ATTEMPTS = 3;
private volatile int maxAttempts;
private BinaryExceptionClassifier retryableClassifier = new BinaryExceptionClassifier();
private BinaryExceptionClassifier fatalClassifier = new BinaryExceptionClassifier();
/**
* Create a {@link SimpleRetryPolicy} with the default number of retry
* attempts.
*/
public SimpleRetryPolicy() {
this(DEFAULT_MAX_ATTEMPTS);
}
private BinaryExceptionClassifier retryableClassifier = new BinaryExceptionClassifier(false);
/**
* Create a {@link SimpleRetryPolicy} with the specified number of retry
* attempts, and default exceptions to retry.
* attempts.
*
* @param maxAttempts number of allowed attempts (typically >= 1)
* @param maxAttempts
* @param retryableExceptions
*/
public SimpleRetryPolicy(int maxAttempts) {
public SimpleRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions) {
super();
Collection<Class<? extends Throwable>> classes;
classes = new HashSet<Class<? extends Throwable>>();
classes.add(Exception.class);
setRetryableExceptionClasses(classes);
classes = new HashSet<Class<? extends Throwable>>();
setFatalExceptionClasses(classes);
this.maxAttempts = maxAttempts;
this.retryableClassifier = new BinaryExceptionClassifier(retryableExceptions);
}
/**
* Setter for retry attempts.
*
* @param retryAttempts the number of attempts before a retry becomes
* impossible.
*/
@@ -90,6 +71,7 @@ public class SimpleRetryPolicy implements RetryPolicy {
/**
* Test for retryable operation based on the status.
*
* @see org.springframework.batch.retry.RetryPolicy#canRetry(org.springframework.batch.retry.RetryContext)
*
* @return true if the last exception was retryable and the number of
@@ -100,27 +82,6 @@ public class SimpleRetryPolicy implements RetryPolicy {
return (t == null || retryForException(t)) && context.getRetryCount() < maxAttempts;
}
/**
* Set the retryable exceptions. Any exception on the list, or subclasses
* thereof, will be retryable. Others will be re-thrown without retry.
*
* @param retryableExceptionClasses defaults to {@link Exception}.
*/
public final void setRetryableExceptionClasses(Collection<Class<? extends Throwable>> retryableExceptionClasses) {
retryableClassifier.setTypes(retryableExceptionClasses);
}
/**
* Set the fatal exceptions. Any exception on the list, or subclasses
* thereof, will be re-thrown without retry. This list takes precedence over
* the retryable list.
*
* @param fatalExceptionClasses defaults to {@link Exception}.
*/
public final void setFatalExceptionClasses(Collection<Class<? extends Throwable>> fatalExceptionClasses) {
fatalClassifier.setTypes(fatalExceptionClasses);
}
/**
* @see org.springframework.batch.retry.RetryPolicy#close(RetryContext)
*/
@@ -142,6 +103,7 @@ public class SimpleRetryPolicy implements RetryPolicy {
* Get a status object that can be used to track the current operation
* according to this policy. Has to be aware of the latest exception and the
* number of attempts.
*
* @see org.springframework.batch.retry.RetryPolicy#open(RetryContext)
*/
public RetryContext open(RetryContext parent) {
@@ -162,6 +124,6 @@ public class SimpleRetryPolicy implements RetryPolicy {
* retryable.
*/
private boolean retryForException(Throwable ex) {
return !fatalClassifier.classify(ex) && retryableClassifier.classify(ex);
return retryableClassifier.classify(ex);
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.batch.retry.support;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
@@ -73,7 +74,8 @@ public class RetryTemplate implements RetryOperations {
private volatile BackOffPolicy backOffPolicy = new NoBackOffPolicy();
private volatile RetryPolicy retryPolicy = new SimpleRetryPolicy();
private volatile RetryPolicy retryPolicy = new SimpleRetryPolicy(3, Collections
.<Class<? extends Throwable>, Boolean> singletonMap(Exception.class, true));
private volatile RetryListener[] listeners = new RetryListener[0];
@@ -81,6 +83,7 @@ public class RetryTemplate implements RetryOperations {
/**
* Public setter for the {@link RetryContextCache}.
*
* @param retryContextCache the {@link RetryContextCache} to set.
*/
public void setRetryContextCache(RetryContextCache retryContextCache) {
@@ -91,6 +94,7 @@ public class RetryTemplate implements RetryOperations {
* Setter for listeners. The listeners are executed before and after a retry
* block (i.e. before and after all the attempts), and on an error (every
* attempt).
*
* @param listeners
* @see RetryListener
*/
@@ -100,6 +104,7 @@ public class RetryTemplate implements RetryOperations {
/**
* Register an additional listener.
*
* @param listener
* @see #setListeners(RetryListener[])
*/
@@ -111,6 +116,7 @@ public class RetryTemplate implements RetryOperations {
/**
* Setter for {@link BackOffPolicy}.
*
* @param backOffPolicy
*/
public void setBackOffPolicy(BackOffPolicy backOffPolicy) {
@@ -195,7 +201,7 @@ public class RetryTemplate implements RetryOperations {
// Allow the retry policy to initialise itself...
RetryContext context = open(retryPolicy, state);
logger.debug("RetryContext retrieved: "+context);
logger.debug("RetryContext retrieved: " + context);
// Make sure the context is available globally for clients who need
// it...