[SpringBatch 실습] 3. Batch Job 수행시 Step 실패하는 경우

반응형
728x90
반응형

Job 생성

JobExecutionConfiguration.java
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.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=JobExecutionTestJob
 */

@Configuration
@RequiredArgsConstructor
public class JobExecutionConfiguration {
    // job 생성
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job JobExecutionTestJob() {
        return this.jobBuilderFactory.get("JobExecutionTestJob")
                /* step start */
                .start(JobExecutionTestStep1())
                .next(JobExecutionTestStep2())
                .build();
    }

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

    @Bean
    public Step JobExecutionTestStep2() {
        return stepBuilderFactory.get("JobExecutionTestStep2")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                        System.out.println("JobExecutionTestStep2 was executed");
                        /** 에러 발생 */
                        throw new RuntimeException("step2 has failed"); // 에러 발생시키기
//                        return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }
}

 

JobExecutionTestStep2 에서 고의로 에러를 발생시켰다.

.tasklet(new Tasklet() {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println("JobExecutionTestStep2 was executed");
        /** 에러 발생 */
        throw new RuntimeException("step2 has failed"); // 에러 발생시키기
//                        return RepeatStatus.FINISHED;
    }
})

 

  • 결과
java.lang.RuntimeException: step2 has failed
at com.project.springbatch._3.JobExecutionConfiguration$2.execute(JobExecutionConfiguration.java:76) ~[main/:na]

 

 

DB 테이블 조회

1) BATCH_JOB_EXECUTION

COLUMN VALUE
STATUS FAILED
EXIT_CODE FAILED

 

2) BATCH_JOB_INSTANCE

COLUMN VALUE
JOB_NAME JobExecutionTestJob

 

3) BATCH_STEP_EXECUTION

  • JobExecutionTestStep1
COLUMN VALUE
STEP_NAME JobExecutionTestStep1
EXIT_CODE COMPLETED
STATUS COMPLETED

 

  • JobExecutionTestStep2
COLUMN VALUE
STEP_NAME JobExecutionTestStep2
EXIT_CODE FAILED
STATUS FAILED

 

 

해당 Job을 다시 수행한다면?

고의로 오류를 발생시켰던 코드를 정상적으로 종료되도록 수정하자.

@Bean
public Step JobExecutionTestStep2() {
    return stepBuilderFactory.get("JobExecutionTestStep2")
            .tasklet(new Tasklet() {
                @Override
                public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                    System.out.println("JobExecutionTestStep2 was executed");
                    /** 에러 발생 */
//                        throw new RuntimeException("step2 has failed"); // 에러 발생시키기
                    return RepeatStatus.FINISHED;
                }
            })
            .build();
}

 

SpringBatch 에서는 동일한 Job을 동일한 파라미터로 수행하면 아래와 같은 메시지가 출력되는게 맞다.

Step already complete or not restartable, so no action to execute: StepExecution: id=3, version=3, name=helloStep1, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=

Step already complete or not restartable, so no action to execute: StepExecution: id=4, version=3, name=helloStep2, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=

하지만 이번 경우에는 정상적으로 Job이 수행되었다.

위 처음 Job을 수행했을때의 결과를 보면 Job이 FAILED 상태로 종료되었기 때문이다.

 

1) BATCH_JOB_EXECUTION

COLUMN VALUE
STATUS COMPLETED
EXIT_CODE COMPLETED

 

2) BATCH_JOB_INSTANCE

  • 위 처음 실행했을때와 데이터가 새로 INSER 되지 않는다.
  • 동일한 Job일때 jobInstance는 재사용한다. (동일한 Job : 동일한 파라미터로 COMPLETED Job 수행)
COLUMN VALUE
JOB_NAME JobExecutionTestJob

 

3) BATCH_STEP_EXECUTION

  • JobExecutionTestStep1

이미 성공한 Job이므로 다시 수행되지 않는다.

 

  • JobExecutionTestStep2

COMPLETED 상태로 JobExecutionTestStep2의 데이터가 INSERT 되었다.

COLUMN VALUE
STEP_NAME JobExecutionTestStep2
EXIT_CODE COMPLETED
STATUS COMPLETED

 

 

한번더, 해당 Job을 다시 수행한다면?

이제 Job이 성공되었고, 동일한 파라미터로 수행시 아래와 같은 메시지가 출력된다.

Step already complete or not restartable, so no action to execute: StepExecution: id=19, version=3, name=JobExecutionTestStep1, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
Step already complete or not restartable, so no action to execute: StepExecution: id=22, version=3, name=JobExecutionTestStep2, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=

 

 

 

반응형

Designed by JB FACTORY