How to run read () function only once Spring Package

I am creating a Spring batch job followed by xml:

<batch:job id="simulatorJob" restartable="false"> <batch:step id="step1"> <batch:tasklet transaction-manager="transactionManager"> <batch:chunk reader="stockListner" writer="customWriter" commit-interval="5"> </batch:chunk> </batch:tasklet> </batch:step> </batch:job> <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" /> <bean id="stockListner" class="com.XXX.stock.java.StockReader" scope="step"> <property name="URL" value="NTPC,TCS" /> <!-- <property name="URL" value="NTPC" /> --> <!-- <property name="URL" value="TCS" /> --> </bean> <bean id="customWriter" class="com.XXX.stock.java.FlatFileWriter" /> 

This is my reader class:

 private String URL; public String getURL() { return URL; } public void setURL(String uRL) { URL = uRL; } public ArrayList<StockData> read() throws Exception, UnexpectedInputException,ParseException, NonTransientResourceException { ArrayList<StockData> list = new ArrayList<StockData>(); String[] splitStocks = URL.split(","); for(int i=0; i < splitStocks.length;i++){ list.add(stockReader.getStockData(splitStocks[i])); } return list; } 

But the reader class continues to work. How can I stop at the first start?

I tried this:

 public StockData read() throws Exception, UnexpectedInputException,ParseException, NonTransientResourceException { ArrayList<StockData> list = new ArrayList<StockData>(); String[] splitStocks = URL.split(","); for(int i=0; i < splitStocks.length;i++) { return stockReader.getStockData(splitStocks[i]); } return null; } 

The read () function goes into a loop.

+6
source share
3 answers

This simple delegate encapsulates a one-time read.

 class OneItemReader<T> implements ItemReader<T> { boolean read = false; ItemReader<T> delegate; @Override public T read() { if(read) { return null; } T item = delegate.read(); read = true; return item; } } 

You can create your reader without thinking about a single reading and wrap it with this small delegate.

Your StockURLReader may be defined as

 class StockURLReader implements ItemReader<StockReader> { String[] tokens = new String[0]; int index = 0; StockDAO stockReader; void setURL(String URL) { this.tokens = URL.split(","); index = 0; } StockData read() { if(index < tokens.length) { return stockReader.getStockData(tokens[index++]); } return null; } } 

Create OneTimeReader and set StockURLReader as the delegate, and you have a separate reading of StockData from the one-time reading logic.
If you want to read the StockData group, the best solution would be to create a StockDataListBean , where you save all the StockData read from the fragmented URL.

 class StockDataListBean { List<StockData> data = new LinkedList<StockData>(); } 

and change StockURLReader as:

 class StockURLReader implements ItemReader<StockDataListBean> { String[] URLs = new String[0]; int index; StockDAO stockReader; void setURLs(String[] URL) { this.URLs = URL; index = 0; } StockDataListBean read() { StockDataListBean item = null; if(index < URLs.length) { item = new StockDataListBean(); for(String token : URLs[index].split(",").length) { item.data.add(stockReader.getStockData(token)); } } return item; } } 
+4
source

Quoting ItemReader.read() Javadoc:

Reads part of the input and moves on to the next. Implementations should return null at the end of the input dataset.

So you need to return null after the first read to tell Spring Batch that there is nothing more to read.

+4
source

You can use ListIteamReader like this (example, not verified):

 public class StockReader extends ListItemReader<StockData> { public StockReader(String URL) { super(createListFromUrl(URL)); } public List<StockData> createListFromUrl(String URL) { // create your ArrayList<StockData> list from URL } } 
+1
source

All Articles