2011-11-14 30 views
18

我有一個要求,即tasklet將所有文件存儲在arraylist中的目錄中。列表的大小存儲在作業執行上下文中。稍後在另一個步驟中從另一個任務小程序訪問此計數。它是如何做到這一點的。我試着在jobexecution背景下存儲,在運行時會引發不可修改收集例外,從tasklet存儲在JobExecutionContext中並在另一個tasklet中訪問

public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) 
throws Exception { 
    StepContext stepContext = arg1.getStepContext(); 
    StepExecution stepExecution = stepContext.getStepExecution(); 
    JobExecution jobExecution = stepExecution.getJobExecution(); 
    ExecutionContext jobContext = jobExecution.getExecutionContext(); 
    jobContext.put("FILE_COUNT",150000); 

也存儲在beforestep註釋的stepexection參考.still不possioble.kindly讓我知道,如何將兩個微進程之間共享數據。

回答

43

至少有4種可能性:

  1. 使用ExecutionPromotionListener到pass data to future steps
  2. 使用(彈簧)豆保持級間數據,例如即ConcurrentHashMap
    • 沒有進一步的行動這一數據將無法訪問的重新啓動
  3. 訪問JobExecutionContext在你的tasklet,應謹慎使用,會引起線程問題的並行步驟
  4. 使用新的jobscope

代碼例從微進程訪問JobExecution(與彈簧批次3引入):

  1. 設定值

    public class ChangingJobExecutionContextTasklet implements Tasklet { 
    
        /** {@inheritDoc} */ 
        @Override 
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 
         // set variable in JobExecutionContext 
         chunkContext 
           .getStepContext() 
           .getStepExecution() 
           .getJobExecution() 
           .getExecutionContext() 
           .put("value", "foo"); 
    
         // exit the step 
         return RepeatStatus.FINISHED; 
        } 
    
    } 
    
  2. 提取值

    public class ReadingJobExecutionContextTasklet implements Tasklet { 
    
        private static final Logger LOG = LoggerFactory.getLogger(ChangingJobExecutionContextTasklet.class); 
    
        /** {@inheritDoc} */ 
        @Override 
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 
         // pull variable from JobExecutionContext 
         String value = (String) chunkContext 
                .getStepContext() 
                .getStepExecution() 
                .getJobExecution() 
                .getExecutionContext() 
                .get("value"); 
    
         LOG.debug("Found value in JobExecutionContext:" + value); 
    
         // exit the step 
         return RepeatStatus.FINISHED; 
        } 
    } 
    

i的my spring-batch-examples github repository創建代碼示例,第一3級的解決方案見模塊複雜和打包interstepcommunication

+0

謝謝,我會看看這個。我想從JobExecutionDecider bean中提取jobexecutioncontext中的值 –

+0

@MichaelLange:爲什麼原始Suresh的代碼拋出異常?它在語義上與您提供的代碼片段相同。 –

+0

它應該工作,我只是猜測他使用'chunkContext.getStepContext()。getJobExecutionContext()。put(...)'之前,這將拋出不可修改的異常 –

4

另一種方法是使用步驟執行後調用的StepExecutionListener。 您的tasklet可以實現它並共享本地屬性。

public class ReadingJobExecutionContextTasklet implements Tasklet, StepExecutionListener { 
    private String value; 

    @Override 
    public ExitStatus afterStep(StepExecution stepExecution) { 
     ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext(); 

     jobExecutionContext.put("key", value); 
     //Return null to leave the old value unchanged. 
     return null; 
    } 
} 

所以,在這一步中,你的bean是一個tasklet和一個像bellow一樣的監聽器。 你還應該配置你的步驟範圍爲「步驟」:

<batch:step id="myStep" next="importFileStep"> 
     <batch:tasklet> 
      <ref bean="myTasklet"/> 
      <batch:listeners> 
       <batch:listener ref="myTasklet"/> 
      </batch:listeners> 
     </batch:tasklet> 
    </batch:step> 

    <bean id="myTasklet" class="ReadingJobExecutionContextTasklet" scope="step"> 
相關問題