사용자 도구

사이트 도구


springframework:springboot:batch

SpringBoot와 SpringBatch

아래는 SpringBoot 에서 명령행(Command line)으로 Spring Batch Job을 실행하는 방법이다.

의존성 및 bootJar 설정

compile('org.springframework.boot:spring-boot-starter-batch')
 
// 2.x
bootJar {
    mainClassName = "my.boot.batch.BatchApplication"
}
 
// 1.x - 지정하지 않으면 자동으로 @SpringBootApplication 애노테이션이 붙은 클래스로 자동 지정됨.
bootRepackage {
    mainClass = "my.boot.batch.BatchApplication"
}

BatchApplication 구성

  • starter 의 org.springframework.boot.autoconfigure.batch.BatchAutoConfigurationorg.springframework.boot.autoconfigure.batch.BasicBatchConfigurer 를 분석해보면 작동 원리를 알 수 있다.
  • 올바르게 Boot Auto Configuration 을 사용하려면 JobLauncherCommandLineRunner Bean을 생성해줘야 한다.
  • JobLauncherCommandLineRunner
    • spring.batch.job.enabled=true일 때 자동 생성되며, spring.batch.job.names 에 쉼표로 구분되어 지정된 Job들을 실행한다. 단, spring.batch.job.names가 존재하지 않으면 모든 Job을 실행해버린다!
    • @EnableBatchProcessing에 의해 생성된 JobLauncher, JobExplorer를 주입받고,
    • Program 인자로 param1=value1 param2=value2로 준 값이 자동으로 Job Parameter key/value로 들어가게 된다.
  • 기본적으로 @Primary DataSource를 자동으로 사용한다. 보통 이 경우 문제가 된다. 별도 DB를 따로 사용하게 설정하려면 Spring Framework Batch 에서 설정 Override 참조.
@Slf4j
@EnableBatchProcessing
@SpringBootApplication
@Import(각종기타 설정 import)
public class BatchApplication extends DefaultBatchConfigurer {
    public static void main(String[] args) {
        int exitCode = SpringApplication.exit(SpringApplication.run(BatchApplication.class, args));
        System.exit(exitCode);
    }
 
    @Value("${spring.batch.job.names:NONE}")
    private String jobNames;
 
    // 어디선가 미리 생성해둔 spring batch 용 database
    @Autowired
    @Override
    public void setDataSource(@Qualifier("batchDataSource") DataSource batchDataSource) {
        super.setDataSource(batchDataSource);
    }
 
    // spring.batch.job.names 를 지정하지 않으면 모든 Job이 실행돼 버리기 때문에
    // 방어차원에서 넣은 job.names validation 처리    
    @PostConstruct
    public void validateJobNames() {
        log.info("jobNames : {}", jobNames);
        if (jobNames.isEmpty() || jobNames.equals("NONE")) {
            throw new IllegalStateException("spring.batch.job.names=job1,job2 형태로 실행을 원하는 Job을 명시해야만 합니다!");
        }
    }
}
DefaultBatchConfigurer 사용시에 이 클래스내에서 transactionManager를 batchDataSource 용으로 생성해버려서 원래 애플리케> 이션의
DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration 가 작동하지 않게 된다.
따라서 항상 애플리케이션용 DataSource에 대한 transactionManager를 항상 명시적으로 만들어주고 @Primary 설정을 해줘야 한다.

예제 Batch Job Configuration

@Slf4j
@Configuration
// 아래를 통해 실행 대상 job으로 들어갔을 때만 해당 Job 설정이 수행되게 하면 불필요한 설정 부담을 줄일 수 있고
// 실수로 job이 실행되는 것을 막을 수 있다.
@ConditionalOnProperty(name = "spring.batch.job.names", havingValue = "helloJob")
public class HelloBatchConfiguration {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
 
    public HelloBatchConfiguration() {
        // job.names가 helloJob 일 때만 생성자의 아래 로그가 출력됨.
        log.info("======== Hello Job configured!! ==========");
    }
 
    @Bean(name = "helloJob")
    public Job helloJob() {
        return jobBuilderFactory.get("helloJob")
                .start(step())
                .build();
    }
 
    @Bean
    public Step step() {
        return stepBuilderFactory.get("taskletStep").tasklet(new Tasklet() {
 
            @Override
            public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                log.info("==== Tasklet called....");
                Map<String, Object> jobParameters = chunkContext.getStepContext().getJobParameters();
                // 모든 Job Parameter 출력
                jobParameters.forEach((key, value) -> {
                    log.info("key : {}, value : {}", key, value);
                });
                return RepeatStatus.FINISHED;
            }
        }).build();
    }
 
}

application.properties/yml

  • spring.batch.job.enabled=true 여야 JobLauncherCommandLineRunner가 활성화 된다.
spring:
  batch:
    job:
      enabled: true
    initialize-schema: embedded
  main:
    web-application-type: NONE
  • spring.batch.initialize-schema 는 거의 항상 embdded로 지정하며, 별도 DB 사용시에는 never로 지정한다. always인 경우는 거의 없다고 봄.
  • SpringBoot 2.x 기준, spring-boot-starter-web, spring-boot-starter-webflux가 의존성에 없어야 하며, 만약 있다면 spring.main.web-application-type=NONE으로 설정할 것.
  • Spring Batch 를 integraition test 할 때 spring.batch.job.enabled=false 로 두고 JobLauncherTestUtils 로 런칭하게 하지 않으면 배치 Job이 두 번 실행된다. 첫번째 실행시 파라미터가 잘못 주입된다.

실행

bootJar로 jar를 생성하고

gradle bootJar
java -jar your-boot.jar --spring.batch.job.names=${JOB이름} \
    JobParam1=ParamValue1 JobParam2=ParamValue2
  • spring.batch.job.names는 쉼표로 구분하여 여러개도 지정 가능하다.
  • spring.batch.job.names를 명시하지 않으면 모든 job 이 다 실행된다.

완전 auto configuration

  • 완전히 AutoConfig 로 SpringBoot batch 를 설정할 때 @org.springframework.boot.autoconfigure.batch.BatchDataSource 를 사용하여 batch 용 dataSource 지정이 가능하다.

spring-boot-starter-batch-web

참고

springframework/springboot/batch.txt · 마지막으로 수정됨: 2021/09/06 16:06 저자 kwon37xi