Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run read() function only once Spring Batch

I am creating a Spring Batch job with folowing 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 keeps on running. How do I stop at first run?

I tried this aswell:

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 loop..

like image 974
Amaresh Avatar asked Oct 27 '15 12:10

Amaresh


People also ask

How do I stop a Spring Batch reader?

To terminate a step you have to return null from ItemReader. read() so when you process an old object you can set a flag into step-execution context and use it to: prevent other items of current chunk to be processed. prevent chunk processed item writing.

What is skip limit in Spring Batch?

Skipping ItemsDefine a skip-limit on your chunk element to tell Spring how many items can be skipped before the job fails (you might handle a few invalid records, but if you have too many then the input data might be invalid).

How do I read a file in Spring Batch?

Reading flat files in the Spring Batch framework is facilitated by the class called FlatFileItemReader , which provides basic functionality for reading and parsing flat files. The two most important required dependencies of FlatFileItemReader are Resource and LineMapper .

What is StepExecution in Spring Batch?

public class StepExecution extends Entity. Batch domain object representation the execution of a step. Unlike JobExecution , there are additional properties related the processing of items such as commit count, etc.


2 Answers

This simple delegate encapsulate one-time reading.

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 you own reader without think about one-time reading and wrap it using 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 delegate and you have separate StockData reading from one-time reading logic.
If you want to read a group of StockData the best solution is to create a StockDataListBean where you store all StockData read from a splitted URL.

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

and modify 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;
  }
}
like image 62
Luca Basso Ricci Avatar answered Sep 19 '22 07:09

Luca Basso Ricci


Quoting ItemReader.read() Javadoc:

Reads a piece of input data and advance to the next one. Implementations must return null at the end of the input data set.

As such, you need to return null after the first read to indicate to Spring Batch that there is nothing more to read.

like image 28
Tunaki Avatar answered Sep 19 '22 07:09

Tunaki