1

I am looking for help to find out a way to set job execution context in my chunk Listener.

 @Bean
  public Step testStep(
      JdbcCursorItemReader<TestStep> testStageDataReader,
      TestStepProcessor testStepProcessor,
      CompositeItemWriter<Writer> testWriter,
      PlatformTransactionManager transactionManager,
      JobRepository jobRepository, TestChunkListener testChunkListener) {
    return stepBuilderFactory
        .get("TESTING")
        .<>chunk(100)
        .reader(testStageDataReader)
        .processor(testStepProcessor)
        .writer(testWriter)
        .faultTolerant()
        .skip(DataIntegrityViolationException.class)
        .skipLimit(4)
        .listener(testSkipListener)
        .transactionManager(transactionManager)
        .repository(jobRepository)
        .build();
  }

The Skip Listener

@Component
@RequiredArgsConstructor
@Slf4j
@StepScope
public class TestSkipListener {

  private final TestRepository testRepository;
  @Value("#{jobExecutionContext['jobExecutionTestId']}")
  private Long jobExecutionTestId; //this is null

  @OnSkipInWrite
  public void onSkipInWrite(Writer writer,
                            Throwable t) {
    logException(t);

  }
}

I am setting job execution id in

@Component
@Slf4j
@RequiredArgsConstructor
public class TestJobListener extends JobExecutionListenerSupport {

  @Override
  public void beforeJob(JobExecution jobExecution) {
    long jobExecutionId = jobExecution.getJobId();
    jobExecution.getExecutionContext()
                .put("jobExecutionTestId", jobExecutionId);
  }
}

This works fine in my Processor and Writer but at skip listener, it is coming as null

JDev
  • 1,662
  • 4
  • 25
  • 55
  • In your `testStep` method you have a `TestChunkListener testChunkListener` parameter, but in the step definition you are registering a `.listener(testSkipListener)`. You shared the code of `TestSkipListener` but not the one of `TestChunkListener`. Is it similar to `TestSkipListener` in regards to injecting the id from the job execution context or is this a typo in your question? – Mahmoud Ben Hassine Jun 15 '20 at 11:51

1 Answers1

4

You certainly have found a way after this time. But I was in the same situation, found your post, and finally came up with a solution in my own. Let's share it here for next stuck developers :

You can load the execution context using @Value. The key differs depending on the Scope you put on your class.

@JobScope :

@Component
@JobScope
public class MySkipListener implements SkipListener<T, T> {

    @Value("#{jobExecution.executionContext}")
    private ExecutionContext executionContext;

    @Override
    public void onSkipInRead(Throwable throwable) {
        String myVariableInContext = executionContext.get("myVariableKey");
        // do your stuff
    }

@StepScope :

@Component
@StepScope
public class MySkipListener implements SkipListener<T, T> {

    @Value("#{stepExecution.jobExecution.executionContext}")
    private ExecutionContext executionContext;

    @Override
    public void onSkipInRead(Throwable throwable) {
        String myVariableInContext = executionContext.get("myVariableKey");
        // do your stuff
    }
Anth224
  • 41
  • 4