RESOLVED - issue BATCH-305: ItemProvider still referenced in comments / variable naming in ItemOrientedTasklet
http://jira.springframework.org/browse/BATCH-305
This commit is contained in:
@@ -40,7 +40,7 @@ import org.springframework.util.Assert;
|
||||
* A concrete implementation of the {@link Tasklet} interface that provides
|
||||
* 'split processing'. This type of processing is characterized by separating
|
||||
* the reading and processing of batch data into two separate classes:
|
||||
* ItemProvider and ItemProcessor. The ItemProvider class provides a solid means
|
||||
* {@link ItemReader} and {@link ItemProcessor}. The {@link ItemReader} class provides a solid means
|
||||
* for re-usability and enforces good architecture practices. Because an object
|
||||
* <em>must</em> be returned by the {@link ItemReader} to continue
|
||||
* processing, (returning null indicates processing should end) a developer is
|
||||
@@ -108,7 +108,7 @@ public class ItemOrientedTasklet implements Tasklet, Skippable,
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(itemProvider, "ItemProvider must be provided");
|
||||
Assert.notNull(itemProvider, "ItemReader must be provided");
|
||||
Assert.notNull(itemProcessor, "ItemProcessor must be provided");
|
||||
|
||||
if (itemRecoverer == null && (itemProvider instanceof ItemRecoverer)) {
|
||||
|
||||
@@ -282,7 +282,7 @@ public class ItemOrientedTaskletTests extends TestCase {
|
||||
try {
|
||||
module.afterPropertiesSet();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().toLowerCase().indexOf("provider") >= 0);
|
||||
assertTrue(e.getMessage().toLowerCase().indexOf("reader") >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package org.springframework.batch.item.processor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -6,6 +7,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.batch.restart.Restartable;
|
||||
@@ -17,11 +19,11 @@ import org.springframework.batch.statistics.StatisticsProvider;
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class CompositeItemProcessor implements ItemProcessor, Restartable, StatisticsProvider {
|
||||
|
||||
|
||||
private static final String SEPARATOR = "#";
|
||||
|
||||
private List itemProcessors;
|
||||
|
||||
|
||||
/**
|
||||
* Calls injected ItemProcessors in order.
|
||||
*/
|
||||
@@ -32,15 +34,16 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
}
|
||||
|
||||
/**
|
||||
* Compound restart data of all injected (Restartable) ItemProcessors, property keys are
|
||||
* prefixed with list index of the ItemProcessor.
|
||||
* Compound restart data of all injected (Restartable) ItemProcessors,
|
||||
* property keys are prefixed with list index of the ItemProcessor.
|
||||
*/
|
||||
public RestartData getRestartData() {
|
||||
Properties props = createCompoundProperties(new PropertiesExtractor() {
|
||||
public Properties extractProperties(Object o) {
|
||||
if (o instanceof Restartable) {
|
||||
return ((Restartable)o).getRestartData().getProperties();
|
||||
} else {
|
||||
return ((Restartable) o).getRestartData().getProperties();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -49,24 +52,24 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data contains values of restart data, property keys are expected to be prefixed with
|
||||
* list index of the ItemProcessor.
|
||||
* @param data contains values of restart data, property keys are expected
|
||||
* to be prefixed with list index of the ItemProcessor.
|
||||
*/
|
||||
public void restoreFrom(RestartData data) {
|
||||
if (data == null || data.getProperties() == null) {
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
List restartDataList = parseProperties(data.getProperties());
|
||||
|
||||
|
||||
// iterators would make the loop below less readable
|
||||
for (int i=0; i < itemProcessors.size(); i++) {
|
||||
for (int i = 0; i < itemProcessors.size(); i++) {
|
||||
if (itemProcessors.get(i) instanceof Restartable) {
|
||||
((Restartable) itemProcessors.get(i)).restoreFrom((RestartData) restartDataList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,15 +79,16 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
public Properties getStatistics() {
|
||||
return createCompoundProperties(new PropertiesExtractor() {
|
||||
public Properties extractProperties(Object o) {
|
||||
if (o instanceof StatisticsProvider){
|
||||
if (o instanceof StatisticsProvider) {
|
||||
return ((StatisticsProvider) o).getStatistics();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void setItemProcessors(List itemProcessors) {
|
||||
this.itemProcessors = itemProcessors;
|
||||
}
|
||||
@@ -94,26 +98,26 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
*/
|
||||
private List parseProperties(Properties props) {
|
||||
List restartDataList = new ArrayList(itemProcessors.size());
|
||||
for (int i = 0; i<itemProcessors.size(); i++) {
|
||||
for (int i = 0; i < itemProcessors.size(); i++) {
|
||||
restartDataList.add(new GenericRestartData(new Properties()));
|
||||
}
|
||||
|
||||
|
||||
for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
String key = (String) entry.getKey();
|
||||
String value = (String) entry.getValue();
|
||||
int separatorIndex = key.indexOf(SEPARATOR);
|
||||
int i = Integer.valueOf(key.substring(0, separatorIndex)).intValue();
|
||||
((RestartData)restartDataList.get(i)).getProperties().setProperty(
|
||||
key.substring(separatorIndex + 1), value);
|
||||
((RestartData) restartDataList.get(i)).getProperties()
|
||||
.setProperty(key.substring(separatorIndex + 1), value);
|
||||
}
|
||||
return restartDataList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param extractor used to extract Properties from ItemProviders
|
||||
* @return compound Properties containing all the Properties from injected ItemProcessors
|
||||
* with property keys prefixed by list index.
|
||||
* @param extractor used to extract Properties from {@link ItemReader}s
|
||||
* @return compound Properties containing all the Properties from injected
|
||||
* {@link ItemProcessor}s with property keys prefixed by list index.
|
||||
*/
|
||||
private Properties createCompoundProperties(PropertiesExtractor extractor) {
|
||||
Properties stats = new Properties();
|
||||
@@ -121,7 +125,7 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
for (Iterator iterator = itemProcessors.listIterator(); iterator.hasNext();) {
|
||||
ItemProcessor processor = (ItemProcessor) iterator.next();
|
||||
Properties processorStats = extractor.extractProperties(processor);
|
||||
if (processorStats != null) {
|
||||
if (processorStats != null) {
|
||||
for (Iterator iterator2 = processorStats.entrySet().iterator(); iterator2.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) iterator2.next();
|
||||
stats.setProperty("" + index + SEPARATOR + entry.getKey(), (String) entry.getValue());
|
||||
@@ -131,10 +135,11 @@ public class CompositeItemProcessor implements ItemProcessor, Restartable, Stati
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts information from given object in the form of {@link Properties}. If the information
|
||||
* is not available (e.g. unexpected object class) return null.
|
||||
* Extracts information from given object in the form of {@link Properties}.
|
||||
* If the information is not available (e.g. unexpected object class) return
|
||||
* null.
|
||||
*/
|
||||
private interface PropertiesExtractor {
|
||||
Properties extractProperties(Object o);
|
||||
|
||||
@@ -33,15 +33,10 @@ public class ItemReaderAdapter extends AbstractMethodInvokingDelegator implement
|
||||
return invokeDelegateMethod();
|
||||
}
|
||||
|
||||
//harmless implementation of method required by ItemProvider interface
|
||||
//harmless implementation of method required by ItemReader interface
|
||||
public Object getKey(Object item) {
|
||||
return item;
|
||||
}
|
||||
|
||||
//harmless implementation of method required by ItemProvider interface
|
||||
public boolean recover(Object data, Throwable cause) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public class ValidatingItemReader extends DelegatingItemReader {
|
||||
private Validator validator;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.provider.ItemReaderItemProvider#afterPropertiesSet()
|
||||
* @see org.springframework.batch.item.reader.DelegatingItemReader#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
@@ -38,7 +38,7 @@ public class ValidatingItemReader extends DelegatingItemReader {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.provider.ItemReaderItemProvider#next()
|
||||
* @see org.springframework.batch.item.reader.DelegatingItemReader#read()
|
||||
*/
|
||||
public Object read() throws Exception {
|
||||
Object input = super.read();
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.io.sample.domain.FooService;
|
||||
import org.springframework.batch.item.reader.ItemReaderAdapter;
|
||||
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
|
||||
/**
|
||||
@@ -15,34 +14,33 @@ import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
private ItemReaderAdapter provider;
|
||||
|
||||
|
||||
private FooService fooService;
|
||||
|
||||
|
||||
protected String getConfigPath() {
|
||||
return "delegating-item-provider.xml";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Regular usage scenario - items are retrieved from
|
||||
* the service injected invoker points to.
|
||||
*/
|
||||
* Regular usage scenario - items are retrieved from the service injected
|
||||
* invoker points to.
|
||||
*/
|
||||
public void testNext() throws Exception {
|
||||
List returnedItems = new ArrayList();
|
||||
Object item;
|
||||
while ((item = provider.read()) != null) {
|
||||
returnedItems.add(item);
|
||||
}
|
||||
|
||||
|
||||
List input = fooService.getGeneratedFoos();
|
||||
assertEquals(input.size(), returnedItems.size());
|
||||
assertFalse(returnedItems.isEmpty());
|
||||
|
||||
for (int i = 0; i<input.size(); i++) {
|
||||
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
assertSame(input.get(i), returnedItems.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getKey(..) is implemented trivially.
|
||||
*/
|
||||
@@ -50,13 +48,6 @@ public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInje
|
||||
Object item = new Object();
|
||||
assertSame(item, provider.getKey(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover not supported.
|
||||
*/
|
||||
public void testRecover() {
|
||||
assertFalse(provider.recover(null, null));
|
||||
}
|
||||
|
||||
public void setProvider(ItemReaderAdapter provider) {
|
||||
this.provider = provider;
|
||||
@@ -65,6 +56,5 @@ public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInje
|
||||
public void setFooService(FooService fooService) {
|
||||
this.fooService = fooService;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user