2

Recently, I tried to add a predefined Value with the @Value annotation to a Bean:

@Component
public class TaskletConfig {

  @Bean(name = "FilenameExecutionTasklet")
  @JobScope
  public Tasklet FilenameExecutionTasklet() {
      return new Tasklet() {

          @Value("#{jobParameters['inputFilename']}") 
          private String inputFilename;

          @Value("${platformImport.jobParameter.inputFile}") 
          private String inputFile;

          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

              chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename);
              return RepeatStatus.FINISHED;
        }

    };
  }
}

which ends up in a NullPointerException. If I do (almost) the same in a Tasklet, it works:

@JobScope
@Component
public class FilenameExecutionTasklet implements Tasklet {

  @Value("${platformImport.jobParameter.inputFile}")
  private String inputFile;

  @Value("#{jobParameters['inputFilename']}") 
  private String inputFilename;

  @Override
  public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
      chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile, inputFilename);
      return RepeatStatus.FINISHED;
  }
}

Could anybody, please, tell my why? I would have expect both working.

The value of @Value("${platformImport.jobParameter.inputFile}") is in the application.yml.

NPE is thrown in chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename); with inputFile.

Robert Kirsten
  • 474
  • 2
  • 5
  • 12

1 Answers1

1

I believe you are hitting the NPE because late binding and order of evaluation within Spring Batch. Because the FilenameExecutionTasklet competent is in JobScope, it allows Spring Batch to evaluate other beans (those in singleton scope) in the application context BEFORE evaluating the @Value annotation.

I'm not positive on this, but you may be able to either add @JobScope to TaskletConfig or instead move the @Value annotations to be arguements to your bean creation method.

@Component
public class TaskletConfig {

  @Bean(name = "FilenameExecutionTasklet")
  @JobScope
  public Tasklet FilenameExecutionTasklet(
         @Value("#{jobParameters['inputFilename']}") String inputFilename,
         @Value("${platformImport.jobParameter.inputFile} String inputFile ) {

      return new Tasklet() {
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
              chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put(inputFile , inputFilename);
              return RepeatStatus.FINISHED;
        }

    };
  }

}

Outside of that, I'm just not quite sure what your use case is here. If the filename is being provided as a job parameter, what's the point of putting it in the execution context?

In fact the Tasklet will already have access to it via the ChunkContext:

public RepeatStatus execute(final StepContribution Contribution, final ChunkContext chunkContext) throws Exception {
    String fileName;
    //one way
    fileName = chunkContext.getStepContext().getStepExecution().getJobExecution().getJobParameters().getString("inputFileName");
    //another way
    fileName = (String) chunkContext.getStepContext().getJobParameters().get("inputFileName");
    return null;
}
Dean Clark
  • 3,770
  • 1
  • 11
  • 26
  • Hey! Thx for your answer. Your first paragraph sounds reasonable. I am not that deep into spring batch to know what's beneath the surface of all these annotations. Unfortunately, your suggestion putting the @JobScope annotation to the ´TaskletConfig´ Level wasn't right. But, I didn't know that I can access the JobParameters in a similar way then the `ExecutionContext`. Thanks for that. (Reason for upvote.) – Robert Kirsten Jul 04 '16 at 13:31
  • Interesting about the @JobScope placement not having an effect. Out of curiosity, did you also try moving the `@Value` properties to be arguments to the `FilenameExecutionTasklet()` method? – Dean Clark Jul 06 '16 at 17:24