Reputation: 53
I am using a spring batch application which reads a Flat file and returns an object . All i wanted to do is to make the FlatFileItemReader to return a list and pass it to processor and so that it treats each list as one item . Please see the snippet below
@Bean public FlatFileItemReader <List<T>> reader() throws Exception {
//reader.read()
}
@Bean
public ItemProcessor <List<T>, V> getTargetValueProcessor() {
return new ItemProcessor <List<T>, V>() {
@Override
public V process(List<T> t) throws Exception {
//processing logic
}
}; }
But my Item processor treats each item in the list as a single input to the processor and the processor is called the number of times as the list size. If the list size returned by the reader is 3 , the processor is called three times. Any thoughts on how to handle list inputs in ItemProcessor ??
TIA
Upvotes: 2
Views: 15992
Reputation: 190
You can write a Generic Class like below which can be used to Read Multiple Lines at once and pass those as List<T>
to Processor, Hope it helps :)
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.core.io.Resource;
public class FlatFileItemGroupReader<T> implements ResourceAwareItemReaderItemStream<List<T>> {
private int groupSize = 100;
private static final Logger LOG = LogManager.getLogger(FlatFileItemGroupReader.class);
private FlatFileItemReader<T> fileReader;
@Override
public synchronized List<T> read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
List<T> records = new ArrayList<T>();
while(records.size() < groupSize) {
T record = fileReader.read();
if (Objects.isNull(record)) {
break;
}
records.add(record);
}
if (records.isEmpty()) {
return null;
}
return records;
}
@Override
public synchronized void open(ExecutionContext executionContext) throws ItemStreamException {
fileReader.open(executionContext);
}
@Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
}
@Override
public synchronized void close() throws ItemStreamException {
fileReader.close();
}
public FlatFileItemReader<T> getFileReader() {
return fileReader;
}
public void setFileReader(FlatFileItemReader<T> fileReader) {
this.fileReader = fileReader;
}
public int getGroupSize() {
return groupSize;
}
public void setGroupSize(int groupSize) {
this.groupSize = groupSize;
}
@Override
public void setResource(Resource resource) {
this.fileReader.setResource(resource);
}
}
Upvotes: 0
Reputation: 31590
You can find an example of an item reader that returns a List
of objects as a single item here: https://github.com/spring-projects/spring-batch/tree/master/spring-batch-samples#multiline
Here is the implementation: https://github.com/spring-projects/spring-batch/blob/master/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemReader.java#L55
Upvotes: 1