[SpringBatch 실습] 2. ApplicationRunner 구현 클래스로 Job 수행시키기

반응형
728x90
반응형

Job 생성

JobParameterConfiguration.java

파라미터를 출력하는 Job을 생성하자.

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;
import java.util.Map;

/*
--job.name=jobParameterTestJob
 */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class JobParameterConfiguration {
    // job 생성
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job jobParameterTestJob() {
        return this.jobBuilderFactory.get("jobParameterTestJob")
                /* step start */
                .start(jobParameterTestStep1())
                .next(jobParameterTestStep2())
                .build();
    }

    @Bean
    public Step jobParameterTestStep1() {
        return stepBuilderFactory.get("jobParameterTestStep1")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                        System.out.println("jobParameterTestStep1 was executed");

                        /* CASE1. contribution */
                        JobParameters jobParameters = contribution.getStepExecution()
                                .getJobExecution()
                                .getJobParameters();

                        String name = jobParameters.getString("name");
                        Long seq = jobParameters.getLong("seq");
                        Date date = jobParameters.getDate("date");
                        Double doubleParam = jobParameters.getDouble("double");

                        /* CASE2. chunkContext */
                        Map<String, Object> jobParameters1 = chunkContext.getStepContext().getJobParameters();
                        String name2 = (String) jobParameters1.get("name");

                        log.info("name : " + name);
                        log.info("seq : " + seq);
                        log.info("date : " + date);
                        log.info("doubleParam : " + doubleParam);
                        log.info("name2 : " + name2);

                        return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }

    @Bean
    public Step jobParameterTestStep2() {
        return stepBuilderFactory.get("jobParameterTestStep2")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                        System.out.println("jobParameterTestStep2 was executed");
                        return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }
}

 

CASE1. JobParameters 객체

1) StepContribution 의 StepExecution에서 JobExecution의 JobParameters 객체를 얻는다.

JobParameters jobParameters = contribution.getStepExecution()
                                .getJobExecution()
                                .getJobParameters();
                                
String name = jobParameters.getString("name");
Long seq = jobParameters.getLong("seq");
Date date = jobParameters.getDate("date");
Double doubleParam = jobParameters.getDouble("double");

 

CASE2. Map<String, Object> 객체

ChunkContext 의 StepContext에서 JobParameters 객체를 얻는다.

Map<String, Object> jobParameters1 = chunkContext.getStepContext().getJobParameters();
String name2 = (String) jobParameters1.get("name");

 

 

Job 수행 준비

application.yml
spring:
  config:
    activate:
      on-profile: postgresql
  datasource:
    url: jdbc:postgresql://localhost:5432/...
    username: ...
    password: ...
    driver-class-name: org.postgresql.Driver
  batch:
    job:
      enabled: false # spring batch 자동실행 방지
      names: ${job.name:NONE}

 

 

 

Job이 1개인 경우

JobParameterTest.java
package com.project.springbatch._2;

import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component // bean
@RequiredArgsConstructor
public class JobParameterTest implements ApplicationRunner {
    /* 잡을 실행시키는, 스프링부트가 초기화될때 이미 빈으로 생성되어있어서 주입이 가능하다. */
    private final JobLauncher jobLauncher;

    /* xxxConfiguration 안의 Job 이 빈이므로 주입이 가능하다. */
    private final Job job;

    /**
     * Program argument : name=user1 seq(long)=2L date(date)=2021/01/01 double(double)=16.5
     * 이렇게도 가능하다.
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name", "seohae")
                .addLong("seq", 1L)
                .addDate("date", new Date())
                .addDouble("double", 16.5)
                .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}

존재하는 1개의 Job이 수행된다.

 

만약 Job이 2개라면?

아래와 같은 오류 메시지가 console 에 출력된다.

... required a single bean, but 2 were found:

 

 

Job이 2개 이상인 경우

JobParameterMultiTest.java
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component // bean
@RequiredArgsConstructor
public class JobParameterMultiTest implements ApplicationRunner {
    /* 잡을 실행시키는, 스프링부트가 초기화될때 이미 빈으로 생성되어있어서 주입이 가능하다. */
    private final JobLauncher jobLauncher;

    /* xxxConfiguration 안의 Job 이 빈이므로 주입이 가능하다. */
//    private final Job job;

    private final ApplicationContext context;

    /**
     * Program argument : name=user1 seq(long)=2L date(date)=2021/01/01 double(double)=16.5
     * 이렇게도 가능하다.
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        Job job = context.getBean(args.getOptionValues("job.name").get(0), Job.class);

        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name", "seohae")
                .addLong("seq", 1L)
                .addDate("date", new Date())
                .addDouble("double", 16.5)
                .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}

 

1) Job 지정하기

Job job = context.getBean(args.getOptionValues("job.name").get(0), Job.class);

 

결과

name : seohae
seq : 1
date : Sat May 21 19:55:18 KST 2022
doubleParam : 16.5
name2 : seohae

 

 

 

반응형

Designed by JB FACTORY