목차

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 구성

@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
    initialize-schema: embedded
  main:
    web-application-type: NONE

실행

bootJar로 jar를 생성하고

gradle bootJar
java -jar your-boot.jar --spring.batch.job.names=${JOB이름} \
    JobParam1=ParamValue1 JobParam2=ParamValue2

완전 auto configuration

spring-boot-starter-batch-web

참고