从tasklet存储JobExecutionContext并在另一个tasklet中访问

时间:2011-11-14 03:42:18

标签: spring-batch

我需要一个tasklet,将目录中的所有文件存储在arraylist中。列表的大小存储在作业执行上下文中。稍后,在另一个步骤中从另一个tasklet访问此计数。怎么做到这一点。我试图存储在jobexecution上下文中,在运行时抛出不可修改的集合异常,

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

还将stepexection引用存储在beforestep注释中.still not possioble.kindly让我知道,如何在两个tasklet之间共享数据。

2 个答案:

答案 0 :(得分:53)

你至少有4种可能性:

  1. 使用ExecutionPromotionListener到pass data to future steps
  2. 使用(spring)bean来保存步骤间数据,例如ConcurrentHashMap
    • 无需进一步操作,无法重新启动此数据
  3. 访问您的tasklet中的JobExecutionContext,应谨慎使用,否则会导致并行步骤的线程问题
  4. 使用新的jobscope(春季批次3引入)
  5. 从Tasklet访问JobExecution的代码示例:

    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;
          }
      }
      
    3. 我为my spring-batch-examples github repository中的前3个解决方案创建了代码示例,请参阅模块 complex 和package interstepcommunication

答案 1 :(得分:5)

另一种方法是使用在步骤执行后调用的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">