Storing in JobExecutionContext from tasklet and accessing in another tasklet
Another way is to use StepExecutionListener
which is called after step execution.
Your tasklet can implements it and share local attribute.
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;
}
}
So, in the step, your bean is a tasklet and a listener like bellow. You should also configure the scope of you step to "step" :
<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">
you have at least 4 possibilities:
- use the ExecutionPromotionListener to pass data to future steps
- use a (spring) bean to hold inter-step data, e.g. a ConcurrentHashMap
- without further action this data won't be accessible for a re-start
- access the JobExecutionContext in your tasklet, should be used with caution, will cause thread problems for parallel steps
- use the new jobscope (introduced with spring batch 3)
Code Example for accessing JobExecution from Tasklet:
setting a value
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; } }
extracting a value
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 created code examples for the first 3 solutions in my spring-batch-examples github repository, see module complex and package interstepcommunication