Spring Batch Job의 구성

Spring Batch Job

  • 하나의 논리적인 배치작업을 의미합니다.
  • 배치작업을 어떻게 구성하고, 실행할것인지 명세해놓은 객체입니다.
  • 배치 작업을 구성하기 위한 최상위 인터페이스이며, Spring Batch가 기본 구현체를 제공합니다.
  • 여러 Step으로 구성될 수 있으며, 반드시 하나 이상의 Step으로 구성해야 합니다.
    ( Job - Step의 관계는 일대다관계입니다)

Job의 구현체

  • Spring Batch에서 제공하는 Job의 구현체는 2가지 종류가 있습니다.
  1. Simple Job : 순차적으로 Step을 실행시키는 Job을 의미합니다.
  2. Flow Job : 조건별로 분기를 따라 Step을 구성하여 실행시키는 Job을 의미합니다.

Job 구성방법

  • Spring Batch에서는 Job과 Step을 Spring Bean으로 관리한다. 때문에 @Configuration 설정 클래스에서 Job 객체를 등록해줄 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Bean
public Job helloJob() { // 1. Job 구성
return jobBuilderFactory.get("helloJob")
.start(helloStep1())
.next(helloStep2())
.build();
}
@Bean
public Step helloStep1() {// 2. Step 구성
return stepBuilderFactory.get("helloStep1")
.tasklet(((contribution, chunkContext) -> {
System.out.println("##### step1");
return RepeatStatus.FINISHED;
}))
.build();
}
@Bean
public Step helloStep2() {
return stepBuilderFactory.get("helloStep2")
.tasklet(((contribution, chunkContext) -> {
System.out.println("###### step2");
return RepeatStatus.FINISHED;
}))
.build();
}

Job Launcher 와 Job Parameter

  • JobLaunder 배치 작업을 실행하는 역할을 합니다.
  • JobParameter와 Job을 인자로 받아서 실행합니다.
[1] Job Launder Sequence Diagram
  • 예시코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Component
public class JobRunner implements ApplicationRunner {

private final Job job;
private final JobLauncher jobLauncher;

public JobRunner(Job job, JobLauncher jobLauncher) {
this.job = job;
this.jobLauncher = jobLauncher;
}

@Override
public void run(ApplicationArguments args) throws Exception {
JobParameters jobParameters = new JobParametersBuilder() // 1. Job Parameter를 생성합니다.
.addString("name", "user1")
.toJobParameters();

jobLauncher.run(job,jobParameters); // 2. Job Launcher가 주어진 Job과 Job Parameter를 받아서 Job을 실행합니다.

}
}

Job Instance

  • Job이 실행될떄 생성되는 Job의 논리적 실행 단위 객체. 즉 작업 실행을 의미한다.
  • Job과 JobInstance는 왜 구분해야 할까?
    • Job의 설정과 구성은 동일하지만 Job이 실행되는 시점에 처리하는 내용은 다르기 때문에 Job의 실행을 구분해야 합니다.
    • JobInstance는 Job과 JobParameter의 조합으로 생성하며, 처음 시작하는 Job과 Job Parameter의 경우는 새로운 Job Instance를 생성합니다.
    • 하나의 Job은 여러번 실행될 수 있으므로 Job과 JobInstance의 연관관계는 1:N의 관계입니다.
  • BATCH_JOB_INSTANCE 테이블에 매핑됩니다.
Job Runner에 의해 Job 실행시 BATCH_JOB_EXECUTION 테이블
  • JobInstance의 경우 동일한 Job과 Job Parameter의 조합인 경우 예외(JobInstanceAlreadyCompleteException)를 던집니다.즉 동일한 Job을 동일한 Job Parameter로 돌리면 중복 JobInstance로 판정됩니다.
    1
    2
    3
    4
    5
    6
    Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={name=user1}.  If you want to run this job again, change the parameters.
    at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:139) ~[spring-batch-core-4.3.9.jar:4.3.9]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]

Job Parameter

  • 말그대로 Job을 실행할 때 함께 포함되어 사용되는 parameter 가진 도메인 객체입니다
  • 하나의 Job안에 존재하는 여러 JobInstance를 구분하기 위한 용도이다. 즉 JobInstance와 JobParameter는 1:1 관계입니다. (테이블 관계에서는 1:N)
  • BATCH_JOB_EXECUTION_PARAM 테이블과 매핑됩니다.
  • Spring Batch에서는 STRING, DATE, LONG, DOUBLE 타입을 지원을 하며, BATCH_JOB_EXECUTION_PARAM 테이블에서 타입별로 칼럼을 가지고 있습니다.

Job Parameter 생성방식

  1. Application 생성 시점에 외부 환경변수로 주입되는 방법

빌드한 Jar파일에 다음과 같이 외부 매개변수로 KEY-VALUE 형태로 값을 주입해줄 수 있다. 이떄 문자형이 아닌 경우는 별도로 (타입명)을 지정해주어야 합니다. 혹은 program argument로 key=value형태로 넣어줄 수 있습니다.

1
java -jar spring-batch-0.0.1-SNAPSHOT.jar name=cs seq\(long\)=2L date\(date\)=2023/10/27 age\(double\)=3 
  1. Application Code에서 직접 생성하는 방법
    1
    2
    3
    4
    5
    6
    JobParameters parameters = new JobParametersBuilder()
    .addString("name", "chansoo")
    .addLong("seq", 1l)
    .addDate("date", new Date())
    .addDouble("age", 16.5)
    .toJobParameters();
Job Runner에 의해 Job 실행시 BATCH_JOB_EXECUTION_PARAMS 테이블
  • 값을 주지 않으면 DATE_VAL의 경우는 기본값으로 1970-01-01 09:00:00, STRING_VAL의 경우 빈 문자열('') , LONG & DOUBLE_VAL의 경우는 0이 들어갑니다.
  1. SpEL 문법을 통해 생성하는 방법

Job Parameter를 꺼내오는 법

  1. Tasklet Based Step
  • tasklet의 경우는 StepContribution, ChunkContext 클래스에서 모두 JobParameter를 꺼내올 수 있습니다.
  • 차이점은 StepContribution은 JobParameters 타입의 객체를 반환하고, ChunkContext의 경우 Map 타입의 객체를 반환하는 차이점이 있습니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Bean
    public Step step1() {
    return stepBuilderFactory.get("step1")
    .tasklet((contribution, chunkContext) -> {
    JobParameters params = contribution.getStepExecution().getJobExecution()
    .getJobParameters();
    String name = params.getString("name");
    Long seq = params.getLong("seq");
    Date date = params.getDate("date");
    Double age = params.getDouble("age");

    Map<String, Object> jobParameters = chunkContext.getStepContext()
    .getJobParameters();
    return RepeatStatus.FINISHED;
    })
    .build();
    }

Job Execution

  • Job Instance에 대한 한번의 시도를 의미하는 객체로서 Job 실행 중에 발생한 정보들을 저장하고 있는 객체입니다
  • 즉 Job Instance와 Job Execution은 1:N의 관계입니다. (한번의 Job Instance가 여러번 실행될 수 있음으로)
  • 작업 시작시간, 작업 종료시간, 작업의 실행 결과 상태값(시작/완료/실패/종료)속성을 가집니다.
    • Job Execution 의 상태 결과가 COMPLETED 라면 Job Instance의 실행이 완료된것으로 간주하여 재실행이 불가능합니다. (JobInstanceAlreadyCompleteException예외가 던져집니다.)
    • Job Execution 의 상태 결과가 FAILED 라면 COMPLETED가 될떄까지 하나의 Job Instance를 여러번 재실행할 수 있습니다. (동일한 Job parameter라도 재시작이 가능합니다, 재실행될떄마다 BATCH_JOB_EXECUTION_PARAMS 테이블에 Job parameter 정보가 누적됩니다)
  • BATCH_JOB_EXECUTION 테이블과 매핑됩니다.
BATCH JOB 실패시 BATCH_JOB_EXECUTION 테이블(하나의 Job Instance에 대해 여러개의 FAIL상태값을 가질 수 있습니다.)

Reference

Comments