예제로 배우는 핵심 Spring Batch

Ch07. 여러개의 step 구동 및 실행 상태에 따른 분기처리

webmaster 2023. 6. 10. 20:11
728x90

여러 개의 STEP

https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#SequentialFlow

 

Spring Batch - Reference Documentation

If a group of Steps share similar configurations, then it may be helpful to define a “parent” Step from which the concrete Steps may inherit properties. Similar to class inheritance in Java, the “child” Step combines its elements and attributes wit

docs.spring.io

MultipleStepJobConfig

/**
 * desc: 다중 step을 사용하기 및 step to step 데이터 전달 run: --spring.batch.job.name=multipleStepJobConfig
 */
@Configuration
@RequiredArgsConstructor
public class MultipleStepJobConfig {

  private final JobBuilderFactory jobBuilderFactory;

  private final StepBuilderFactory stepBuilderFactory;

  @Bean
  public Job multipleStepJob(Step multipleStep1, Step multipleStep2, Step multipleStep3) {
    return jobBuilderFactory.get("multipleStepJob")
        .incrementer(new RunIdIncrementer())
        .start(multipleStep1) //여러개의 step을 단계별로 등록
        .next(multipleStep2)
        .next(multipleStep3)
        .build();
  }

  @Bean
  @JobScope
  public Step multipleStep1() {
    return stepBuilderFactory.get("multipleStep1")
        .tasklet(((contribution, chunkContext) -> {
          System.out.println("step1");
          return RepeatStatus.FINISHED;
        }))
        .build();
  }

  @Bean
  @JobScope
  public Step multipleStep2() {
    return stepBuilderFactory.get("multipleStep2")
        .tasklet(((contribution, chunkContext) -> {
          System.out.println("step2");

          ExecutionContext executionContext = chunkContext
              .getStepContext()
              .getStepExecution()
              .getJobExecution()
              .getExecutionContext();

          executionContext.put("someKey", "hello!!"); //필요한 key 값으로 데이터 등록

          return RepeatStatus.FINISHED;
        }))
        .build();
  }

  @Bean
  @JobScope
  public Step multipleStep3() {
    return stepBuilderFactory.get("multipleStep3")
        .tasklet(((contribution, chunkContext) -> {
          System.out.println("step3");

          ExecutionContext executionContext = chunkContext
              .getStepContext()
              .getStepExecution()
              .getJobExecution()
              .getExecutionContext();

          System.out.println(executionContext.get("someKey")); //필요한 key 값을 가지고 오기

          return RepeatStatus.FINISHED;
        }))
        .build();
  }
}
  • 여러 개의 Step을 실행시킬 수 있다.
    • Job을 생성할 때, Step을 next()에 여러 개 추가할 수 있다.
  • Step끼리의 데이터는 StepContext.StepExecution.JobExecution.ExecutionContext에 넣어서 공유할 수 있다.
    • put 메서드로 someKey라는 Key로 hello!!! 데이터를 넣었다.
    • get 메서드로 someKey 값을 가지고 왔다.

분기처리 스텝 실행

https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#conditionalFlow

 

Spring Batch - Reference Documentation

If a group of Steps share similar configurations, then it may be helpful to define a “parent” Step from which the concrete Steps may inherit properties. Similar to class inheritance in Java, the “child” Step combines its elements and attributes wit

docs.spring.io

/**
 * desc: step 결과의 따른 다음 step 분기 처리 run param: --spring.batch.job.names=conditionalStepJob
 */
@Configuration
@RequiredArgsConstructor
public class ConditionalStepJobConfig {


  private final JobBuilderFactory jobBuilderFactory;

  private final StepBuilderFactory stepBuilderFactory;


  @Bean
  public Job conditionalStepJob(
      Step conditionalStartStep,
      Step conditionalAllStep,
      Step conditionalFailStep,
      Step conditionalCompletedStep) {
    return jobBuilderFactory.get("conditionalStepJob")
        .incrementer(new RunIdIncrementer())
        .start(conditionalStartStep)
        .on("FAILED").to(conditionalFailStep) //분기처리 가능 //실패일 경우
        .from(conditionalStartStep)
        .on("COMPLETED").to(conditionalCompletedStep) //성공일 경우
        .from(conditionalStartStep)
        .on("*").to(conditionalAllStep) //모든 스텝 적용
        .end()
        .build();
  }

  @Bean
  @JobScope
  public Step conditionalStartStep() {
    return stepBuilderFactory.get("conditionalStartStep")
        .tasklet(new Tasklet() {
          @Override
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
              throws Exception {
            System.out.println("conditional Start Step");
            return RepeatStatus.FINISHED;
            //throw new Exception("Exception");
          }
        }).build();
  }
  @Bean
  @JobScope
  public Step conditionalFailStep() {
    return stepBuilderFactory.get("conditionalFailStep")
        .tasklet(new Tasklet() {
          @Override
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
              throws Exception {
            System.out.println("conditional Fail Step");
            return RepeatStatus.FINISHED;
          }
        }).build();
  }

  @Bean
  @JobScope
  public Step conditionalCompletedStep() {
    return stepBuilderFactory.get("conditionalCompletedStep")
        .tasklet(new Tasklet() {
          @Override
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
              throws Exception {
            System.out.println("conditional Completed Step");
            return RepeatStatus.FINISHED;
          }
        }).build();
  }


  @Bean
  @JobScope
  public Step conditionalAllStep() {
    return stepBuilderFactory.get("conditionalAllStep")
        .tasklet(new Tasklet() {
          @Override
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
              throws Exception {
            System.out.println("conditional All Step");
            return RepeatStatus.FINISHED;
          }
        }).build();
  }
}
  • on() 메서드를 통해 배치가 실패, 성공, 모든 경우의 케이스 별로 원하는 step을 실행시킬 수 있다(분기 처리)
    • FAIL 일 경우 conditionalFailStep이 실행이 된다.
    • COMPLETED 일 경우 conditionalCompletedStep이 실행이 된다.
    • 그 외 모든 경우, conditionalAllStep이 실행이 된다.
728x90