스프링 배치 3.0 이상 버전을 이용하므로 @EnableBatchProcessing이 필요하지 않다
기본 배치 어플리케이션
지난번에 만든 스프링배치 프로젝트 활용
lombok 설정
과정
- Tasklet 구현체 생성
- @Configuration 을 통해서 생성할 Batch Bean을 스프링에 등록한다.
- Job, Step을 생성하고 빈에 등록
- 실행 결과 확인
Tasklet 구현체 생성
Tasklet → Step 내에서 구성되고 실행되는 도메인 객체, 단일 task를 수행하기 위해 사용된다.
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
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.beans.factory.InitializingBean;
@Slf4j
public class GreetingTasklet implements Tasklet, InitializingBean {
@Override
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception{
log.info("======================Taks Execute======================");
log.info("GreetingTask: {}, {}", contribution, chunkContext);
return RepeatStatus.FINISHED;
}
@Override
public void afterPropertiesSet() throws Exception{
log.info("====================== After Properties Sets()=====================");
}
}
- Tasklet, InitializingBean 인터페이스 구현
- Tasklet → execute()
- StepContribution , ChunkContext 를 파라미터로 받음
- RepeatStatus 를 반환한다.
- FINISHED : tasklet 종료
- CONTINUABLE : 계속 태스크 수행
- continueIf(condition) : 조건에 따라 종료/지속 결정
- InitializingBean → afterPropertiesSet()
- Task를 수행 시 프로퍼티를 설정하고 난 뒤에 수행되는 메서드.
- 없어도 됨
@Configuration 을 통해서 생성할 배치 빈을 스프링에 등록하기
@Slf4j
@Configuration
public class BasicTaskJobConfiguration {
}
- 부트업되면 @Configuration 을 찾고 빈 등록 작업을 수행한다.
Job, Step 생성 및 빈 등록
//프로그래밍적 트랜잭션: PlatformTransactionManager 구현체를 Bean에 넘긴다.
//TransactionDefinition, TransacntionStatus를 사용해서 롤백, 커밋
@Autowired
PlatformTransactionManager transactionManager;
@Bean
public Tasklet greetingTasklet() {
return new GreetingTasklet();
}
- 이전에 생성한 Tasklet도 빈으로 등록
- PlatformTransactionManager transactionManager
step bean 등록
@Bean
public Step step(JobRepository jobRepository, PlatformTransactionManager transactionManager){
log.info("=======================Init step=======================");
return new StepBuilder("myStep", jobRepository)
.tasklet(greetingTasklet(), transactionManager)
.build();
}
- JobRepository와 PlatformTransactionManager를 파라미터로 받는다.
- 데이터 소스와 함께 작업
- StepBuilder로 myStep이란 이름의 스텝을 jobRepository에 저장한다.
- tasklet을 step에 추가하고, greetingTasklet() 을 통해서 step 내 tasklet 주입
- build를 통해 step을 생성하고 빈으로 등록, 리턴한다.
Step 기본 구현 클래스
이 코드에선 Tasklet()을 사용해서 구현하는데, 우린 greetingTasklet()을 만들어놨기에 이를 주입해서 사용한다.
StepBuilderFactory는 StepBuilder를 생성하는 팩토리 클래스.
- StepBuilderFactory.get(”stepName”)
- “stepName”으로 step 생성
- @Bean public Step step() { return stepBuilderFactory.get("step") .tasklet(new Tasklet() { @Override public RepeatStatus execute(StepContribution contribution, ChunkContex chunkContext) throws Exception { return RepeatStatus.FINISHED; } }) .build();
Job 등록
@Bean
public Job myJob(Step step, JobRepository jobRepository){
log.info("======================Init job=======================");
return new JobBuilder("myJob", jobRepository)
.incrementer(new RunIdIncrementer())
.start(step)
.build();
}
- step, jobRepository가 파라미터로 들어간다.
- Job은 JobRepository에 등록된다.
- JobBuilder로 myJob이라는 이름의 job을 생성한다.
- incrementer 는 job이 지속적으로 실행될 때, job의 unique성을 구분할 수 있는 방법을 설정한다.
- RunIdIncrementer는 job의 아이디를 실행할 때 지속적으로 증가시키면서 유니크한 잡을 실행하게 된다.
- start()를 통해서 job의 시작 포인트를 잡고, 우리가 파리미터로 받은 step을 등록했다.
- 마찬가지로 build를 통해서 job 생성하고 빈으로 등록하도록 리턴한다.
실행
/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=61517:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/classes:/Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/resources:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/ec547ef414ab1d2c040118fb9c1c265ada63af14/lombok-1.18.34.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-batch/3.3.4/38f47d83bf881149c3995af421779a0071014499/spring-boot-starter-batch-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/com.h2database/h2/2.2.224/7bdade27d8cd197d9b5ce9dc251f41d2edc5f7ad/h2-2.2.224.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-jdbc/3.3.4/b6bc324d5af04af752a6f3e44ea8e4cd96b28343/spring-boot-starter-jdbc-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/3.3.4/f02312a6816fb439a55d2920b9af8f0f8abf5bac/spring-boot-starter-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.batch/spring-batch-core/5.1.2/461b30be2f5e0daaa7fb96e9fbcb98b2a1c12e24/spring-batch-core-5.1.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jdbc/6.1.13/11811219be3452cfd989c57d3de4529f6927352f/spring-jdbc-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/com.zaxxer/HikariCP/5.1.0/8c96e36c14461fc436bb02b264b96ef3ca5dca8c/HikariCP-5.1.0.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/3.3.4/979234a0f3035fe60d5e505018789f98a7ec7ee3/spring-boot-autoconfigure-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/3.3.4/f06c6950aa5766b63328e821641f5c7d71be819d/spring-boot-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/3.3.4/c83073c0f5574b2146695ab716bcef3d6baa45e6/spring-boot-starter-logging-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/2.1.1/48b9bda22b091b1f48b13af03fe36db3be6e1ae3/jakarta.annotation-api-2.1.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/6.1.13/ddbd765408d2665f47017c8f05a7682012f91da3/spring-core-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/2.2/3af797a25458550a16bf89acc8e4ab2b7f2bfce0/snakeyaml-2.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.batch/spring-batch-infrastructure/5.1.2/bfc8439a45a0681f44771d3b15f5c61fe4751db7/spring-batch-infrastructure-5.1.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/6.1.13/d5163ddae069c5d78c841cd3a60c4db25bf16401/spring-context-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/6.1.13/ad2c631e1717fdc6d91d56c06d4fd61e0215c19a/spring-aop-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-tx/6.1.13/ed041ecf9a5f480e1b11d0b58a06d8034ff8cfea/spring-tx-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/6.1.13/90bbee6278b46b145e64e5ae29316bdd459c6826/spring-beans-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-core/1.13.4/6a333b0ac647afa33616e142797da950ff295b7b/micrometer-core-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-observation/1.13.4/2673c9b181ab2512002b23b7ad0f1dd02212696c/micrometer-observation-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.16/172931663a09a1fa515567af5fbef00897d3c04/slf4j-api-2.0.16.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.5.8/229bb1ef6b14dfbf74ff443af9097d836dc5f0dd/logback-classic-1.5.8.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.23.1/425ad1eb8a39904d2830e907a324e956fb456520/log4j-to-slf4j-2.23.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/2.0.16/6d57da3e961daac65bcca0dd3def6cd11e48a24a/jul-to-slf4j-2.0.16.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/6.1.13/37291ff008a66a9dbf2c98e11bd468cfadaa7ebc/spring-jcl-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.retry/spring-retry/2.0.9/fc605474a6002a501a6d0ea67c04df1db14d22af/spring-retry-2.0.9.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/6.1.13/be30254712ca0549cbd539ba05c57064917253f3/spring-expression-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-commons/1.13.4/edcf69518a4c382c48e19c7fb7d4aedfb115c0c3/micrometer-commons-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.5.8/3fce599197de3b6f387cc9bee412ead2b4994a46/logback-core-1.5.8.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.23.1/9c15c29c526d9c6783049c0a77722693c66706e1/log4j-api-2.23.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.hdrhistogram/HdrHistogram/2.2.2/7959933ebcc0f05b2eaa5af0a0c8689fa257b15c/HdrHistogram-2.2.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.latencyutils/LatencyUtils/2.0.3/769c0b82cb2421c8256300e907298a9410a2a3d3/LatencyUtils-2.0.3.jar org.kchabin.springbatch.SpringBatchApplication
. ____ _ __ _ _
/\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
\\\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.4)
2024-10-14T19:23:42.466+09:00 INFO 26389 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : Starting SpringBatchApplication using Java 17.0.7 with PID 26389 (/Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/classes started by kchabin in /Users/kchabin/Desktop/spring-textbook/spring-batch)
2024-10-14T19:23:42.467+09:00 INFO 26389 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : No active profile set, falling back to 1 default profile: "default"
2024-10-14T19:23:42.599+09:00 INFO 26389 --- [spring-batch] [ main] o.s.b.c.c.annotation.BatchRegistrar : Finished Spring Batch infrastructure beans configuration in 1 ms.
2024-10-14T19:23:42.689+09:00 WARN 26389 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' of type [org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:23:42.720+09:00 INFO 26389 --- [spring-batch] [ main] o.kchabin.springbatch.GreetingTasklet : ====================== After Properties Sets()=====================
2024-10-14T19:23:42.728+09:00 INFO 26389 --- [spring-batch] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-10-14T19:23:42.798+09:00 INFO 26389 --- [spring-batch] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
2024-10-14T19:23:42.799+09:00 INFO 26389 --- [spring-batch] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2024-10-14T19:23:42.804+09:00 INFO 26389 --- [spring-batch] [ main] o.s.b.c.r.s.JobRepositoryFactoryBean : No database type set, using meta data indicating: H2
2024-10-14T19:23:42.812+09:00 INFO 26389 --- [spring-batch] [ main] o.k.s.BasicTaskJobConfiguration : =======================Init step=======================
2024-10-14T19:23:42.822+09:00 INFO 26389 --- [spring-batch] [ main] .c.a.BatchObservabilityBeanPostProcessor : No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP
2024-10-14T19:23:42.823+09:00 INFO 26389 --- [spring-batch] [ main] o.k.s.BasicTaskJobConfiguration : ======================Init job=======================
2024-10-14T19:23:42.825+09:00 INFO 26389 --- [spring-batch] [ main] .c.a.BatchObservabilityBeanPostProcessor : No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP
2024-10-14T19:23:42.826+09:00 INFO 26389 --- [spring-batch] [ main] o.s.b.c.l.support.SimpleJobLauncher : No TaskExecutor has been set, defaulting to synchronous executor.
2024-10-14T19:23:42.870+09:00 INFO 26389 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : Started SpringBatchApplication in 0.594 seconds (process running for 0.917)
2024-10-14T19:23:42.872+09:00 INFO 26389 --- [spring-batch] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2024-10-14T19:23:42.873+09:00 INFO 26389 --- [spring-batch] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
종료 코드 0(으)로 완료된 프로세스
After Properties Sets → Init step → Init job 순으로 실행됨
- No TaskExecutor has been set,
SpringBatchApplication의 @EnableBatchProcessing 제거
배치 3.0 이상부터는 @EnableBatchProcessing 이 필요하지 않은데, 추가해놔서 문제가 생긴 것이라고 추측 → 제거
/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=61742:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/classes:/Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/resources:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.34/ec547ef414ab1d2c040118fb9c1c265ada63af14/lombok-1.18.34.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-batch/3.3.4/38f47d83bf881149c3995af421779a0071014499/spring-boot-starter-batch-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/com.h2database/h2/2.2.224/7bdade27d8cd197d9b5ce9dc251f41d2edc5f7ad/h2-2.2.224.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-jdbc/3.3.4/b6bc324d5af04af752a6f3e44ea8e4cd96b28343/spring-boot-starter-jdbc-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/3.3.4/f02312a6816fb439a55d2920b9af8f0f8abf5bac/spring-boot-starter-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.batch/spring-batch-core/5.1.2/461b30be2f5e0daaa7fb96e9fbcb98b2a1c12e24/spring-batch-core-5.1.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jdbc/6.1.13/11811219be3452cfd989c57d3de4529f6927352f/spring-jdbc-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/com.zaxxer/HikariCP/5.1.0/8c96e36c14461fc436bb02b264b96ef3ca5dca8c/HikariCP-5.1.0.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/3.3.4/979234a0f3035fe60d5e505018789f98a7ec7ee3/spring-boot-autoconfigure-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/3.3.4/f06c6950aa5766b63328e821641f5c7d71be819d/spring-boot-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/3.3.4/c83073c0f5574b2146695ab716bcef3d6baa45e6/spring-boot-starter-logging-3.3.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/2.1.1/48b9bda22b091b1f48b13af03fe36db3be6e1ae3/jakarta.annotation-api-2.1.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/6.1.13/ddbd765408d2665f47017c8f05a7682012f91da3/spring-core-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/2.2/3af797a25458550a16bf89acc8e4ab2b7f2bfce0/snakeyaml-2.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.batch/spring-batch-infrastructure/5.1.2/bfc8439a45a0681f44771d3b15f5c61fe4751db7/spring-batch-infrastructure-5.1.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/6.1.13/d5163ddae069c5d78c841cd3a60c4db25bf16401/spring-context-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/6.1.13/ad2c631e1717fdc6d91d56c06d4fd61e0215c19a/spring-aop-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-tx/6.1.13/ed041ecf9a5f480e1b11d0b58a06d8034ff8cfea/spring-tx-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/6.1.13/90bbee6278b46b145e64e5ae29316bdd459c6826/spring-beans-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-core/1.13.4/6a333b0ac647afa33616e142797da950ff295b7b/micrometer-core-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-observation/1.13.4/2673c9b181ab2512002b23b7ad0f1dd02212696c/micrometer-observation-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.16/172931663a09a1fa515567af5fbef00897d3c04/slf4j-api-2.0.16.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.5.8/229bb1ef6b14dfbf74ff443af9097d836dc5f0dd/logback-classic-1.5.8.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.23.1/425ad1eb8a39904d2830e907a324e956fb456520/log4j-to-slf4j-2.23.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/2.0.16/6d57da3e961daac65bcca0dd3def6cd11e48a24a/jul-to-slf4j-2.0.16.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/6.1.13/37291ff008a66a9dbf2c98e11bd468cfadaa7ebc/spring-jcl-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework.retry/spring-retry/2.0.9/fc605474a6002a501a6d0ea67c04df1db14d22af/spring-retry-2.0.9.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/6.1.13/be30254712ca0549cbd539ba05c57064917253f3/spring-expression-6.1.13.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-commons/1.13.4/edcf69518a4c382c48e19c7fb7d4aedfb115c0c3/micrometer-commons-1.13.4.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.5.8/3fce599197de3b6f387cc9bee412ead2b4994a46/logback-core-1.5.8.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.23.1/9c15c29c526d9c6783049c0a77722693c66706e1/log4j-api-2.23.1.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.hdrhistogram/HdrHistogram/2.2.2/7959933ebcc0f05b2eaa5af0a0c8689fa257b15c/HdrHistogram-2.2.2.jar:/Users/kchabin/.gradle/caches/modules-2/files-2.1/org.latencyutils/LatencyUtils/2.0.3/769c0b82cb2421c8256300e907298a9410a2a3d3/LatencyUtils-2.0.3.jar org.kchabin.springbatch.SpringBatchApplication
. ____ _ __ _ _
/\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
\\\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.4)
2024-10-14T19:35:09.253+09:00 INFO 26527 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : Starting SpringBatchApplication using Java 17.0.7 with PID 26527 (/Users/kchabin/Desktop/spring-textbook/spring-batch/out/production/classes started by kchabin in /Users/kchabin/Desktop/spring-textbook/spring-batch)
2024-10-14T19:35:09.254+09:00 INFO 26527 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : No active profile set, falling back to 1 default profile: "default"
2024-10-14T19:35:09.444+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.455+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.456+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceConfiguration' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.456+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'jdbcConnectionDetails' of type [org.springframework.boot.autoconfigure.jdbc.PropertiesJdbcConnectionDetails] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.462+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [com.zaxxer.hikari.HikariDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.464+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.466+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration' of type [org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.467+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionExecutionListeners' of type [org.springframework.boot.autoconfigure.transaction.ExecutionListenersTransactionManagerCustomizer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.468+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties' of type [org.springframework.boot.autoconfigure.transaction.TransactionProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.468+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'platformTransactionManagerCustomizers' of type [org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.470+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionManager' of type [org.springframework.jdbc.support.JdbcTransactionManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.470+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.batch-org.springframework.boot.autoconfigure.batch.BatchProperties' of type [org.springframework.boot.autoconfigure.batch.BatchProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-10-14T19:35:09.472+09:00 WARN 26527 --- [spring-batch] [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$SpringBootBatchConfiguration' of type [org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$SpringBootBatchConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [jobRegistryBeanPostProcessor] is declared through a non-static factory method on that class; consider declaring it as static instead.
2024-10-14T19:35:09.476+09:00 INFO 26527 --- [spring-batch] [ main] o.kchabin.springbatch.GreetingTasklet : ====================== After Properties Sets()=====================
2024-10-14T19:35:09.481+09:00 INFO 26527 --- [spring-batch] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-10-14T19:35:09.549+09:00 INFO 26527 --- [spring-batch] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:testdb user=SA
2024-10-14T19:35:09.550+09:00 INFO 26527 --- [spring-batch] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2024-10-14T19:35:09.581+09:00 INFO 26527 --- [spring-batch] [ main] o.k.s.BasicTaskJobConfiguration : =======================Init step=======================
2024-10-14T19:35:09.591+09:00 INFO 26527 --- [spring-batch] [ main] o.k.s.BasicTaskJobConfiguration : ======================Init job=======================
2024-10-14T19:35:09.639+09:00 INFO 26527 --- [spring-batch] [ main] o.k.springbatch.SpringBatchApplication : Started SpringBatchApplication in 0.524 seconds (process running for 0.695)
2024-10-14T19:35:09.640+09:00 INFO 26527 --- [spring-batch] [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: []
2024-10-14T19:35:09.656+09:00 INFO 26527 --- [spring-batch] [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=myJob]] launched with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}]
2024-10-14T19:35:09.665+09:00 INFO 26527 --- [spring-batch] [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [myStep]
2024-10-14T19:35:09.668+09:00 INFO 26527 --- [spring-batch] [ main] o.kchabin.springbatch.GreetingTasklet : ======================Taks Execute======================
2024-10-14T19:35:09.668+09:00 INFO 26527 --- [spring-batch] [ main] o.kchabin.springbatch.GreetingTasklet : GreetingTask: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING], ChunkContext: attributes=[], complete=false, stepContext=SynchronizedAttributeAccessor: [], stepExecutionContext={batch.version=5.1.2, batch.taskletType=org.kchabin.springbatch.GreetingTasklet, batch.stepType=org.springframework.batch.core.step.tasklet.TaskletStep}, jobExecutionContext={batch.version=5.1.2}, jobParameters={run.id=1}
2024-10-14T19:35:09.672+09:00 INFO 26527 --- [spring-batch] [ main] o.s.batch.core.step.AbstractStep : Step: [myStep] executed in 6ms
2024-10-14T19:35:09.673+09:00 INFO 26527 --- [spring-batch] [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=myJob]] completed with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}] and the following status: [COMPLETED] in 13ms
2024-10-14T19:35:09.675+09:00 INFO 26527 --- [spring-batch] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2024-10-14T19:35:09.690+09:00 INFO 26527 --- [spring-batch] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
종료 코드 0(으)로 완료된 프로세스
After Properties Set ~ Task Execute 까지 잘 실행되는 것을 확인할수 있다.
Spring Batch Architecture
스프링 배치 모델
Tasklet model
- 단순한 처리 모델을 가지고 있으며, 로직 자체가 단순한 경우에 주로 사용한다.
- 다양한 데이터 소스나 파일을 한번에 처리해야 하는 경우 유연함이 있다.
Chunk model
- 데이터양이 매우 큰 경우 효과적으로 처리 가능하다.
- Reader/Processor/Writer 플로우 방식으로 처리된다.
Job
스프링 배치에서 일괄 적용을 위한 일련의 프로세스를 요약하는 단일 실행 단위
Step
- Job과 Step은 1:N 관계이다.
- 하나의 Job에 여러 Step을 재사용, 병렬화, 조건분기 등을 수행할 수 있다.
- Step은 tasklet 모델/chunk 모델의 구현체가 탑재되어 실행된다.
JobLauncher
- Job을 수행하기 위한 인터페이스. 사용자에 의해 직접 수행된다.
- CommandLineJobRunner 를 실행하여 단순하게 배치 프로세스가 수행될 수 있다.
ItemReader
- chunk 단위 모델에서 사용, 소스 데이터를 읽어들이는 역할 수행
ItemProcessor
- 읽어들인 청크 데이터를 처리한다.
- 데이터 변환 수행, 데이터 정제 등의 역할 담당
- 옵션
ItemWriter
- chunk 데이터를 읽어들였거나, 처리된 데이터를 실제 쓰기작업을 담당한다.
- 데이터베이스로 저장, 수정 역할, 파일로 처리 결과를 출력할 수도 있음
Tasklet
- 단순하고 유연하게 배치 처리를 수행하는 task 수행
JobRepository
- Job과 step의 상태를 관리하는 시스템
- 스프링 배치에서 사용하는 테이블 스키마를 기반으로 상태정보를 저장하고 관리한다.
스프링배치 흐름
Main Processing Flow
- JobLauncher는 JobScheduler로부터 초기화된다.
- JobLauncher에서 Job이 execute.
- Job에서 Step이 실행된다.
- Step은 ItemReader를 사용해서 input data를 가져온다.
- 가져온 input data를 ItemProcessor를 사용해서 처리한다.
- Step은 ItemWriter로 처리된 데이터를 출력한다.
Job 정보의 흐름
- JobLauncher는 JobRepository를 통해서 JobInstance 정보를 데이터베이스에 등록한다.
- JobLauncher는 JobRepository를 통해서 DB에 시작된 Job execution을 등록한다. → Job 수행, 실행 정보를 데이터베이스에 저장한다.
- JobStep은 JobRepository를 통해서 I/O 레코드 수 및 상태정보를 업데이트한다.
- job이 완료되면 JobRepository를 통해서 데이터베이스에 완료 정보를 저장한다.
스프링배치 저장 정보
JobInstance
- 잡 이름과 전달 파라미터에 의해 정의된다.
- 동일한 Job name과 argument는 동일한 JobInstance으로 식별되고, Job은 이전 activation의 연속으로 실행된다.
- 중단되는 경우 다음 실행 시 중단 이후부터 실행하도록 지원
- Job이 재실행을 지원하지 않거나, 성공적으로 처리된 경우 배치를 재실행한다면 중복 수행되지 않도록 종료함.
JobExecution / ExecutionContext
- JobExecution
- Job의 물리적인 실행을 나타냄
- JobInstance와 달리 동일한 Job이 여러번 수행될 수 있음. → JobInstacne와 JobExecution은 1:N 관계
- ExecutionContext
- 각각의 JobExecution에서 처리 단계와 같은 메타 정보들을 공유하는 영역.
- 주로 스프링배치가 프레임워크 상태를 기록하는데 사용하며, 애플리케이션에서 ExecutionContest에 접근하는 수단도 제공된다.
- 저장되는 객체는 java.io.Serialized 를 구현하는 클래스여야 한다.
StepExecution
- StepExecution
- Step의 물리적인 실행
- Job은 여러 Step을 수행하는 1:N 관계이다.
- ExecutionContext
- Step 내부에 데이터를 공유해야 하는 공유 영역
- 데이터의 지역화 관점 → 여러 단계에 공유할 필요없는 정보는 Step 내의 ExecutionContext를 사용해야 한다.
- 저장되는 데이터는 반드시 java.io.Serializable 을 구현해야 한다.
JobRepository
- JobExecution, StepExecution 등과 같이 배치 실행정보나 상태, 결과정보들이 데이터베이스에 저장될 때 처리하는 것
- → 스프링배치를 수행하기 위해 이를 저장할 DB가 필요하다.
- 저장된 정보를 활용하여 스프링배치는 배치 잡을 재실행하거나, 정지된 상태 후부터 수행할 수 있는 수단을 제공한다.
'Spring > Spring Batch' 카테고리의 다른 글
Spring Batch (1) : 스프링 배치 빠르게 시작하기 (1) | 2024.10.08 |
---|