[SpringBatch 실습] 18. Job, Flow 혼용하여 Job 수행시키기

반응형
728x90
반응형

Job 생성

import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
--job.name=startNextJob
 */

@Configuration
@RequiredArgsConstructor
public class StartNextConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job startNextJob() {
        return this.jobBuilderFactory.get("startNextJob")
                .start(flowA())// step1, step2
                .next(startNextStep3())
                .next(flowB()) // step4, step5
                .next(startNextStep6())
                .end()
                .build();
    }

    @Bean
    public Flow flowA() {
        FlowBuilder<Flow> flowBuilder = new FlowBuilder<>("flowA");
        flowBuilder.start(startNextStep1())
                .next(startNextStep2())
                .end();

        return flowBuilder.build();
    }

    @Bean
    public Flow flowB() {
        FlowBuilder<Flow> flowBuilder = new FlowBuilder<>("flowA");
        flowBuilder.start(startNextStep4())
                .next(startNextStep5())
                .end();

        return flowBuilder.build();
    }

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

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

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

    @Bean
    public Step startNextStep4() {
        return stepBuilderFactory.get("startNextStep4")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                        System.out.println("startNextStep4");

                        // 고의 에러 발생
                        // JOB FAILED
                        throw new RuntimeException("step4 was failed");
                        // return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }

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

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

 

 

 

실행 흐름

flowA() startNextStep1()
startNextStep2()
  startNextStep3()
flowB() startNextStep4() -> 고의 에러 발생
startNextStep5()
  startNextStep6()

 

 

 

DB 테이블 조회

1) BATCH_JOB_EXECUTION

COLUMN VALUE
STATUS FAILED
EXIT_CODE FAILED
JOB_EXECUTION_ID 15

 

2) BATCH_JOB_INSTANCE

COLUMN VALUE
JOB_NAME startNextJob

 

3) BATCH_STEP_EXECUTION

  • startNextStep1
COLUMN VALUE
STEP_NAME startNextStep1
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 15

 

  • startNextStep2
COLUMN VALUE
STEP_NAME startNextStep2
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 15

 

  • startNextStep3
COLUMN VALUE
STEP_NAME startNextStep3
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 15

 

  • startNextStep4
COLUMN VALUE
STEP_NAME startNextStep4
EXIT_CODE FAILED
STATUS FAILED
JOB_EXECUTION_ID 15

 

 

 

다시 정상 수행으로 변경

flowA() startNextStep1()
startNextStep2()
  startNextStep3()
flowB() startNextStep4() -> 정상 수행되도록 변경 
startNextStep5()
  startNextStep6()

 

startNextStep4()  변경
@Bean
    public Step startNextStep4() {
        return stepBuilderFactory.get("startNextStep4")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                        System.out.println("startNextStep4");

                        // 고의 에러 발생
                        // JOB FAILED
//                        throw new RuntimeException("step4 was failed");
                         return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }

 

 

 

Job 재수행

이전에 실패했었던 startNextStep4 부터 수행된다.

 

실행 결과
startNextStep4
startNextStep5
startNextStep6

 

 

 

DB 테이블 조회

1) BATCH_JOB_EXECUTION

COLUMN VALUE
STATUS COMPLETED
EXIT_CODE COMPLETED
JOB_EXECUTION_ID 16

 

2) BATCH_JOB_INSTANCE

COLUMN VALUE
JOB_NAME startNextJob

 

3) BATCH_STEP_EXECUTION

  • startNextStep1
COLUMN VALUE
STEP_NAME startNextStep1
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 16

 

  • startNextStep2
COLUMN VALUE
STEP_NAME startNextStep2
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 16

 

  • startNextStep3
COLUMN VALUE
STEP_NAME startNextStep3
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 16

 

  • startNextStep4
COLUMN VALUE
STEP_NAME startNextStep4
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 16

 

  • startNextStep5
COLUMN VALUE
STEP_NAME startNextStep5
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 15

 

  • startNextStep6
COLUMN VALUE
STEP_NAME startNextStep6
EXIT_CODE COMPLETED
STATUS COMPLETED
JOB_EXECUTION_ID 16

 

 

반응형

Designed by JB FACTORY