2015-10-27 48 views
6

Io sono la creazione di un lavoro primavera batch con xml folowing:Come eseguire read() funzione solo una volta in batch Primavera

<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" /> 

Questa è la mia classe lettore:

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;   
} 

Ma la classe reader mantiene sulla corsa. Come mi fermo alla prima corsa?

Ho provato questo 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; 
} 

Il read() funzione va in ciclo ..

risposta

4

Questo semplice delegato incapsulare la lettura di una volta.

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; 
    } 
} 

È possibile creare voi proprio lettore senza pensare lettura circa un ora e avvolgerla utilizzando questo piccolo delegato.

tuo StockURLReader può essere definita come

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; 
    } 
} 

Creare OneTimeReader e impostare StockURLReader come delegato e si dispone di StockData separati da leggere una volta la logica di lettura.
Se si desidera leggere un gruppo di StockData la soluzione migliore è creare un StockDataListBean in cui si memorizzano tutte le letture StockData da un URL diviso.

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

e modificare StockURLReader come:

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; 
    } 
} 
+0

Come questo codice può essere adattato in questo scenario .. – Aman

+0

Credo che @Aman abbia più di una voce' StockData' da leggere a differenza di quanto suggerito dal primo tentativo (cioè dichiarare 'ArrayList read()'). –

+0

controlla la mia modifica ... –

4

Citando ItemReader.read() Javadoc:

Legge un pezzo di dati di input e passare al prossimo. Implementazioni devono restituire null alla fine del set di dati di input.

Come tale, è necessario restituire null dopo la prima lettura per indicare a Spring Batch che non c'è altro da leggere.

+0

Potete per favore fare un esempio come si fa .. – Aman

+0

Il vostro metodo 'read()' deve restituire solo un 'StockData', non una lista. Tieni traccia di quali parti di 'splitStocks 'hai già inviato e restituisci solo un' splitStocks [i] 'finché non c'è più e ritorna' null' (o usa una lista come hai iniziato a fare). –

+0

@Gael Se non è arraylist, come faccio a inviare più valori di Aman

1

È possibile utilizzare un ListIteamReader come questo (ad esempio, non testato):

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 
    } 

}