반응형
728x90
반응형
Job 생성
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.job.DefaultJobParametersExtractor;
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=parentJob
*/
@Configuration
@RequiredArgsConstructor
public class JobStepConfiguration {
// job 생성
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job parentJob() {
return this.jobBuilderFactory.get("parentJob")
.start(jobStep(null))
.next(jobStepStep2())
.build();
}
@Bean
public Step jobStep(JobLauncher jobLauncher) {
return stepBuilderFactory.get("jobStep")
.job(childJob()) // 별도의 메타 job 으로 관리됨
.launcher(jobLauncher)
.parametersExtractor(jobParametersExtractor())
.listener(new StepExecutionListener() {
@Override
public void beforeStep(StepExecution stepExecution) {
// jobParametersExtractor 에서 처리될 파라미터 저장
stepExecution.getExecutionContext().putString("name", "user1");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
})
.build();
}
private DefaultJobParametersExtractor jobParametersExtractor() {
DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();
extractor.setKeys(new String[]{"name"}); // key
return extractor;
}
@Bean
public Job childJob() {
return this.jobBuilderFactory.get("childJob")
.start(jobStepStep1())
.build();
}
@Bean
public Step jobStepStep1() {
return stepBuilderFactory.get("jobStepStep1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("jobStepStep1");
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Step jobStepStep2() {
return stepBuilderFactory.get("jobStepStep2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("jobStepStep2");
return RepeatStatus.FINISHED;
}
})
.build();
}
}
1) 수행 목록
parentJob |
jobStep() 수행 |
jobStepStep2() 수행 | |
jobStep | childJob 수행 |
childJob | jobStepStep1() 수행 |
2) jobStep()
Step에서 별도의 Job을 생성하고 실행한다.
@Bean
public Step jobStep(JobLauncher jobLauncher) {
return stepBuilderFactory.get("jobStep")
.job(childJob()) // 별도의 메타 job 으로 관리됨
.launcher(jobLauncher)
...
}
3) jobParametersExtractor()
Step의 ExecutionContext를 Job이 실행되는데 필요한 JobParameters로 변환하는 방법을 정의한다.
private DefaultJobParametersExtractor jobParametersExtractor() {
DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();
extractor.setKeys(new String[]{"name"}); // key
// name 에 해당하는 key 를 찾는다.
// 그 key 에 해당하는 값들을 가져온다.
return extractor; // user1
}
수행 순서
parentJob |
jobStep() 수행 |
jobStepStep2() 수행 | |
jobStep | childJob 수행 |
childJob | jobStepStep1() 수행 |
- Step 수행 순서
1) jobStepStep1() 수행
2) jobStepStep2() 수행
JobStepStep1() 실패시키기
@Bean
public Step jobStepStep1() {
return stepBuilderFactory.get("jobStepStep1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("jobStepStep1");
throw new RuntimeException("step1 was failed");
// return RepeatStatus.FINISHED;
}
})
.build();
}
수행결과
java.lang.RuntimeException: step1 was failed
ChildJob이 실패하고, ChildJob이 실패함으로써 ParentJob도 실패하게된다.
DB 테이블 조회
1) BATCH_JOB_EXECUTION
JOB_EXECUTION_ID | JOB_NAME | STATUS | EXIT_CODE |
1 | parentJob | FAILED | FAILED |
2 | childJob | FAILED | FAILED |
2) BATCH_JOB_INSTANCE
COLUMN | VALUE |
1 | parentJob |
2 | childJob |
3) BATCH_STEP_EXECUTION
STEP_EXECUTION_ID | STEP_NAME | JOB_EXECUTION_ID | STATUS | EXIT_CODE |
1 | jobStep | 1 | FAILED | FAILED |
2 | jobStepStep1 | 2 | FAILED | FAILED |
1. jobStep 오류 메시지
java.lang.RuntimeException: step1 was failed
2. jobStepStep1 오류 메시지
org.springframework.batch.core.UnexpectedJobExecutionException:
Step failure: the delegate Job failed in JobStep.
JobStepStep1() 성공 / JobStepStep2() 실패시키기
@Bean
public Step jobStepStep2() {
return stepBuilderFactory.get("jobStepStep2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("jobStepStep2");
throw new RuntimeException("step1 was failed");
// return RepeatStatus.FINISHED;
}
})
.build();
}
수행결과
java.lang.RuntimeException: step2 was failed
위 실패한 jobStepStep2()를 수행시키는 Job은 ParentJob이다.
ParentJob은 실패하고, JobStepStep1()을 수행하는 ChildJob은 성공한다.
ParentJob의 Step을 통해 수행된 ChildJob이 실패했으므로 ParentJob도 실패가 되는 것이고, ParentJob만 실패했을 경우에는 ChildJob은 독립적으로 성공할 수 있다.
DB 테이블 조회
1) BATCH_JOB_EXECUTION
JOB_EXECUTION_ID | JOB_NAME | STATUS | EXIT_CODE |
3 | parentJob | FAILED | FAILED |
4 | childJob | COMPLETED | COMPLETED |
2) BATCH_JOB_INSTANCE
COLUMN | VALUE |
1 | parentJob |
2 | childJob |
3) BATCH_STEP_EXECUTION
STEP_EXECUTION_ID | STEP_NAME | JOB_EXECUTION_ID | STATUS | EXIT_CODE |
3 (childJob) | jobStep | 4 | COMPLETED | COMPLETED |
4 (parentJob) | jobStepStep1 | 3 | COMPLETED | COMPLETED |
5 (parentJob) | jobStepStep2 | 3 | FAILED | FAILED |
반응형