0. 이 글의 목적
기존 정수원 님의 강의는 SpringBoot 2.x, Spring-batch 4.x 버전을 사용 중이었으나 최신은 SpringBoot 3.x, Spring-batch 5.x 버전이기에 나는 최신으로 하면서 동작하지 않는 코드와 최신 방법으로 코드를 변형하기 위함
1. Spring Batch의 전략
하나의 Job이 존재하며 이 Job은 여러 Step으로 구성된다. 각 Step에서의 실제 수행은 tasklet에서 이루어진다.
2. 그러면 무엇이 바뀌었는가
우선 StepBuilderFactory와 JobBuilderFactory가 deprecated되었다.
이제 직접 JobBuilder와 StepBuilder를 구현해야 한다.
//@EnableBatchProcessing
@Configuration
@RequiredArgsConstructor
public class HelloJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository, Step helloStep1, Step helloStep2) {
return new JobBuilder("myJob", jobRepository)
.start(helloStep1)
.next(helloStep2)
.build();
}
@Bean
public Step helloStep1(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("helloStep1", jobRepository).tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("======================");
System.out.println(" >> Hello Spring Batch!!");
System.out.println("======================");
return RepeatStatus.FINISHED;
}
}, platformTransactionManager).build();
}
@Bean
public Step helloStep2(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("helloStep2", jobRepository).tasklet((contribution, chunkContext) -> {
System.out.println("======================");
System.out.println(" >>step2 was executed");
System.out.println("======================");
return RepeatStatus.FINISHED;
}, platformTransactionManager).build();
}
}
이 코드에서 job 메서드에 Step이 직접 파라미터로 들어가고 있다. 메서드 이름과 파라미터명이 동일하면 상관이 없지만 이 파라미터 이름을 메서드 이름과 맞춰주지 않으면 직접 Qualifier로 지정을 해줘야 한다.
그리고 나는 현재 @EnableBatchProcessing을 주석처리해 둔 상태이다. 그 이유는 DefaultBatchConfiguration을 상속받으면 사용하지 않아도 된다 나와있기 때문이다.
문제는 저렇게 하는 경우 에러는 발생하지 않지만 수행이 되지 않는다. 무엇이 문제일까.
놀랍게도 spring boot3부터는 EnableBatchProcessing이나 DefaultBatchConfiguration을 사용하면 자동으로 수행하는 것을 막아둔 상태다.
그렇다면 선택지는 2개가 있다. DefaultBatchConfiguration상속을 제거하거나 Runner를 구현해야 한다. 나는 Runner를 구현했다.
이렇게 구현해서 사용하였다.
@Component
public class BatchJobLauncher implements CommandLineRunner {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Override
public void run(String... args) throws Exception {
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Exit status :: " + execution.getStatus());
}
}
아직 에러가 발생한다.
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-07-19T14:34:11.640+09:00 ERROR 26798 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:774) ~[spring-boot-3.1.1.jar:3.1.1]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:755) ~[spring-boot-3.1.1.jar:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:319) ~[spring-boot-3.1.1.jar:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-3.1.1.jar:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-3.1.1.jar:3.1.1]
at com.example.springbatch.SpringBatchApplication.main(SpringBatchApplication.java:15) ~[main/:na]
Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME
FROM BATCH_JOB_INSTANCE
WHERE JOB_NAME = ?
and JOB_KEY = ?]
스키마에 대한 설정이 부족했다. Spring Batch는 메타 데이터에 대한 저장을 위해 6개의 테이블을 필요로 하고 있다.
다행히 이 모든 쿼리를 제공해주고 있다.
인텔리제이 기준 파일 검색으로 schema- 로 검색하여 본인의 db에 맞는 것으로 사용하면 된다.
테이블을 만들었으니 이제 진짜 실행해 보자.
잘된다.
3. 마무리
이제 다음 강의에서 spring batch 4로 되어있는 부분을 다시 5로 바꾸면서 알아갈 생각을 하니 벌써부터 블로그 글감이 떨어지지 않을 것 같아 행복하다.
출처 :
[2] : https://github.com/spring-projects/spring-boot/issues/33435
[3] : https://www.baeldung.com/spring-boot-3-migration#spring-batch