[10회차] 스프링배치 플로우 컨트롤 하기

아래 글은 한국 스프링 사용자 모임(KSUG)에서 진행된 스프링 배치 스터디 내용을 정리한 게시글입니다.
DEVOCEAN에 연재 중인 KIDO님의 글을 참고하여 실습한 내용을 기록했습니다.

 

원본: [SpringBatch 연재 10] 스프링배치 플로우 컨트롤 하기

 

[SpringBatch 연재 10] 스프링배치 플로우 컨트롤 하기

 

devocean.sk.com

 

Spring Batch에서 flow 컨트롤은 Job 내에서 Step들의 실행 순서와 조건을 제어하는 기능입니다.

 

FlowBuilder API를 사용하여 설정할 수 있습니다.

 

주요 API

Flow 컨트롤을 위해 Spring Batch에서 제공하는 주요 API들은 다음과 같습니다.

  • next(): 순차적으로 Step들을 연결시킬 때 사용합니다.
  • on(): 특정 ExitStatus를 감지하여 해당 상태에 따라 흐름을 제어할 때 사용합니다.
  • to(): 다음으로 이동할 Step을 지정합니다.
  • from(): 이벤트 리스너로서, 다음 단계로 넘어가는 조건을 추가로 설정할 때 사용합니다.
  • end(): Flow의 종료를 나타냅니다.

 

next

next()는 다음의 Step으로 이동시키기 위해 사용합니다.

/**
 * 메인 job 실행 메서드
 */
@Bean
public Job nextStepJob(Step step01, Step step02, JobRepository jobRepository) {
    log.info("------------------ Init myJob -----------------");
    return new JobBuilder(NEXT_STEP_TASK, jobRepository)
            .incrementer(new RunIdIncrementer())
            .start(step01)
            .next(step02)
            .build();
}

@Bean(name = "step01")
public Step step01(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    log.info("------------------ Init myStep -----------------");

    return new StepBuilder("step01", jobRepository)
            .tasklet((contribution, chunkContext) -> {
                log.info("Execute Step 01 Tasklet ...");
                return RepeatStatus.FINISHED;
            }, transactionManager)
            .build();
}

@Bean(name = "step02")
public Step step02(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    log.info("------------------ Init myStep -----------------");

    return new StepBuilder("step02", jobRepository)
            .tasklet((contribution, chunkContext) -> {
                log.info("Execute Step 02 Tasklet ...");
                return RepeatStatus.FINISHED;
            }, transactionManager)
            .build();
}

 

on과 from

step의 종료 조건에 따라 어떤 Step으로 이동할지 결정할 수 있도록 합니다.

  • 아래 예시 코드는 step1을 먼저 수행하고, 해당 결과에 따라서 다음 스텝으로 이동합니다.
@Bean
public Job job() {

	  return jobBuilderFactory.get("job")
	      .start(step1())
	      .on("FAILED").to(step3()) // 작업이 실패 할 경우 step3 호출
	      .from(step1()).on("COMPLETED").to(step2()) // step1 작업이 완료 될 경우 step2 호출
	      .end()
	      .build();
}

 

stop

  • 특정 step의 작업 결과 상태를 확인하고 정지합니다.
@Bean
public Job job() {

    return jobBuilderFactory.get("job")
        .start(step1())  // step1의 결과가 실패일 경우 배치 작업을 정지
        .on("FAILED").stop()
        .end()
        .build();
}

job의 실패를 유도하는 예시로 짝/홀수를 사용해 볼 수 있습니다.

@Bean(name = "step01")
public Step step01(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    log.info("------------------ Init myStep -----------------");

    return new StepBuilder("step01", jobRepository)
            .tasklet((contribution, chunkContext) -> {
                log.info("Execute Step 01 Tasklet ...");
                Random random = new Random();
                int randomValue = random.nextInt(1000);

                if (randomValue % 2 == 0) {
                    return RepeatStatus.FINISHED;
                }
                throw new RuntimeException("Error This value is Odd: " + randomValue);
            }, transactionManager)
            .build();
}

stop 예제의 실행 결과

 

1. 짝수 였을 때

step01 실행 후 step02가 실행됩니다.

2024-12-16T20:27:02.031 INFO  Job 'NEXT_STEP_TASK' started with parameters: {'run.id': 2}

2024-12-16T20:27:02.058 INFO  Executing step: 'step01'

2024-12-16T20:27:02.068 INFO  Step 01 Tasklet started
2024-12-16T20:27:02.068 INFO  Random value: 720

2024-12-16T20:27:02.074 INFO  Step 'step01' executed in 14ms

2024-12-16T20:27:02.092 INFO  Executing step: 'step02'

2024-12-16T20:27:02.099 INFO  Step 02 Tasklet started

2024-12-16T20:27:02.104 INFO  Step 'step02' executed in 11ms

2024-12-16T20:27:02.112 INFO  Job 'NEXT_STEP_TASK' completed with status: COMPLETED (Total time: 71ms)

 

2. 홀수 였을 때

step01에서 에러가 발생하고 그대로 종료됩니다.

2024-12-16T20:28:00.820 INFO  Job 'NEXT_STEP_TASK' started with parameters: {'run.id': 5}

2024-12-16T20:28:00.849 INFO  Executing step: 'step01'

2024-12-16T20:28:00.859 INFO  Step 01 Tasklet started
2024-12-16T20:28:00.859 INFO  Random value: 729

2024-12-16T20:28:00.861 ERROR Error occurred in 'step01': java.lang.RuntimeException: Error This value is Odd: 729

2024-12-16T20:28:00.865 INFO  Step 'step01' completed in 15ms

2024-12-16T20:28:00.877 INFO  Job 'NEXT_STEP_TASK' stopped with status: STOPPED (Total time: 47ms)