Spring Batch -@BeforeStep not getting invoked in Partitioner
Asked Answered
C

3

6

We are trying to implement a batch job using spring batch partitioning.In this in "step 2" is a partitioned step where I need some data from step 1 for processing.I used StepExecutionContext which will be promoted to job Execution Context at step1 to store this data.

I tried to use @BeforeStep annotation in partitioner class to get the stepExecutionContext from which I can extract the data stored previously and put it in ExecutionContext of the partitioner .But the method with @BeforeStep annotation is not getting invoked in the partitioner.

Is there any other way to achieve this.

Partitioner Implementation

public class NtfnPartitioner implements Partitioner {

    private int index = 0;
    String prev_job_time  = null;
    String curr_job_time  = null;

    private StepExecution stepExecution ;
    ExecutionContext executionContext ;

    @Override
    public Map<String, ExecutionContext> partition(int gridSize)
    {

           System.out.println("Entered Partitioner");
           List<Integer> referencIds = new ArrayList<Integer>();
           for (int i = 0; i < gridSize;i++) {
            referencIds.add(index++);
           }
           Map<String, ExecutionContext> results = new LinkedHashMap<String,ExecutionContext>();
          for (int referencId : referencIds) {
            ExecutionContext context = new ExecutionContext();
            context.put("referenceId", referencId);
            context.put(NtfnConstants.PREVIOUS_JOB_TIME, prev_job_time);
            context.put(NtfnConstants.JOB_START_TIME, curr_job_time);
            results.put("partition." + referencId, context);
          }
            return results;
        }

    @BeforeStep
    public void beforeStep(StepExecution stepExecution) {
        // TODO Auto-generated method stub
          System.out.println("Entered Before step in partion");
          JobExecution jobExecution = stepExecution.getJobExecution();
          ExecutionContext jobContext = jobExecution.getExecutionContext();
          System.out.println("ExecutionContext"+jobContext);
          String prev_job_time  = (String) jobContext.get(NtfnConstants.PREVIOUS_JOB_TIME);
          String curr_job_time  = (String) jobContext.get(NtfnConstants.JOB_START_TIME);


    }
Cunnilingus answered 6/2, 2014 at 8:29 Comment(2)
did you register NtfnPartitioner as listener in your xml?Ningpo
Do you have @StepScope for your partitioner?Retractor
A
1

The bean should be step scoped.

Java, annotate class:

@StepScope

XML, in bean definition:

scope="step"

Also look at this answer regarding proxied bean (not sure if this applies to you since no other code than the partitioner was provided). In this case you can still add your partitioner as a listener explicitly during step building:

@Autowired
private NtfnPartitioner partitioner;    

...

final Step masterStep = stepBuilderFactory.get("master")
                    .listener(partitioner)
                    .partitioner("slave", partitioner)
                    .step(slave)
                    ...

Or if your partitioner is not bean (e.g. you are creating it based on something dynamic), you can still add it as a listener:

final NtfnPartitioner partitioner = new NtfnPartitioner();    
final Step masterStep = stepBuilderFactory.get("master")
                    .listener(partitioner)
                    .partitioner("slave", partitioner)
                    .step(slave)
                    ...
Arson answered 6/7, 2017 at 18:5 Comment(0)
C
0

To get the handle of Job Parameters you can implement StepExecutionListener to your NtfnPartitioner Class to make use of Overridden methods beforeStep and afterStep. Please make sure that it should be of StepScoped.

public class NtfnPartitioner implements Partitioner, StepExecutionListener {

   String prev_job_time  = null;
   String curr_job_time  = null;
   ....

   @Override
   public Map<String, ExecutionContext> partition(int gridSize)
   {
       ....
       /* Please use prev_job_time and curr_job_time in this 
          method which was fetched from context */
       ....
   }

   @BeforeStep
   public void beforeStep(StepExecution stepExecution) {
         System.out.println("Entered Before step in partion");
         ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext();
         System.out.println("ExecutionContext"+jobContext);
         String prev_job_time  = (String) jobContext.get(NtfnConstants.PREVIOUS_JOB_TIME);
         String curr_job_time  = (String) jobContext.get(NtfnConstants.JOB_START_TIME);

   }

   @Override
   public ExitStatus afterStep(StepExecution stepExecution) {
       if (stepExecution.getStatus() == BatchStatus.COMPLETED) {
           return ExitStatus.COMPLETED;
       }
       return ExitStatus.FAILED;
   }

}
Covarrubias answered 10/4, 2020 at 11:15 Comment(0)
W
0

Thanks to @LucaBassoRicci for his suggestion, I added the partitioner as listener in the step definition:

return stepBuilderFactory
    .get("partitionedStepOne")
    .partitioner(stepOne)
    .partitioner("partition", partitioner())
    .listener(partitioner())
    .taskExecutor(someExecutor())
    .gridSize(SIZE)
    .build();

and left all the rest as above, now it works :)

Witcher answered 30/6, 2023 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.