Spring Batch

Spring Batch 도메인 JobParameters

NEWDODORIPYO 2022. 8. 19. 17:40

기본 개념

  • Job을 실행항 때 함께 포함되어 사용되는 파라미터를 가진 도메인 객체
  • 하나의 Job에 존재할 수 있는 여러개의 JobInstance를 구분하기 위한 용도
    • 하나의 Job에 여러개의 JobInstance 있다는 것은 Job은 하나이지만 JobParameters가 여러개라는 의미이다.
  • JobParameters와 JobInstance는 1:1 관계

BATCH_JOB_EXECUTION_PARAM 테이블과 매핑

  • JOB_EXECUTION 과 1:M 의 관계

JobParameters 구조

JobParameters

  • JobParameter 를 감싸고 있는 Wrapper 클래스 이다
  • 맵으로 <String , JobParameter> Key , 값 으로 데이터가 저장된다

JobParameter

  • JobParameters 가 내부적으로 가지고 있는 JobParameter
  • JobParameter 는 Object 타입의 변수를 가지고있고 거기에 실제로 값을 저장할 수 있다
  • ParameterType 이 라는 Enum 클래스가 있고 Spring Batch 에서 JobParameter 값을 저장할때 타입은 총 4개 있다

ex)

Date , Long , String 타입의 데이터를 저장한다고 가정하면

{"requestDate",new Date()}  {"run.in",2L}  {"name","user"}

👇테이블에는 이렇게 저장된다

BATCH_JOB_EXECUTION_PARAM

job_execution_id type_cd key_name string_val date_val  long_val  double_val identifying
1 DATE requestDate   20220818     Y
1 LONG run.id     2   Y
2 STRING name user        

ParameterType

  • JobParameter 에 저장되는 값을 타입은 총 4가지 이고 String , Date , Long , Double 가있다

코드로 보기

  • Spring Boot 에서 자동으로 실행할 수 있지만 지금은 테스트를 위해 자동 실행이 아닌 수동으로 jobLauncher 를 만들어서 진행 했습니다
    • jobParameter 를 생성해야하기 때문에 이렇게 진행

application.yml

spring:
  profiles:
    active: local

---

spring:
  config:
    activate:
      on-profile: local
  datasource:
    hikari:
      jdbc-url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
      username: sa
      password:
      driver-class-name: org.h2.Driver

---

spring:
  config:
    activate:
      on-profile: mariadb
  datasource:
    url: jdbc:mariadb://localhost:3306/batch
    username: batch
    password: batch
    driver-class-name: org.mariadb.jdbc.Driver
  batch:
    jdbc:
      initialize-schema: always
    job:
      enabled: false
  • job: enabled: false 를 통해서 자동 실행을 막았습니다.

JobConfiguration

<기본적인 step 2개를 만들어줌>

package io.batch;

import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
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;

@Configuration
@RequiredArgsConstructor
public class DBJobConfiguration {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job job(){
        return jobBuilderFactory.get("job")
                .start(step1())
                .next(step2())
                .build();//build를 해주면 실제 Job 생성
    }

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

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

⭐JobParameterTest

<JobParameter 를 Test 하기위한 클래스>

❗어플리케이션 실행시 주입 하는 방법

package io.batch;

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.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JobParameterTest implements ApplicationRunner {

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job job;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name","user1") //String Type
                .addLong("seq",2L) //Long Type
                .addDate("date",new Date()) //Date Type
                .addDouble("age",16.5) //Double Type
                .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}
  • 4가지 Type 타입의 파라미터를 던지고 있다

실행성공

테이블 확인해보기

  • DATE 에 아무런 값을 안주면 1970-01-01 09:00:00.000000 란 값이 주어진다

이제 이렇게 저정한 JobParameter 를 어디서 참조하고 있는지 알아보자

step 단계에서 참조할 수 있는고

stepContributionchunkContext 에서 참조 할 수 있다

stepContribution 안으로 들어가 보면

StepExecution 이 있고 그리고 StepExecution 안으로 들어가보면

JobExecution 이 있다 그리고 다시한번 JobExecution 안으로 들어가보면

**JobParameters 가 있는걸 볼 수 있다**

  • **chunkContext 도 마찬가지다 chunkContext 안에 StepContext 가 있고 그 안에 StepExecution 이 있고 그 안에 JobExecution 이 있다 그리고 그 안에 JobParameters 가 있는걸 확인할 수 있다**

stepContribution 과 chunkContext 둘다 참조가 가능하지만 약간의 차이가 있는데 이건 구현을 해보면서 알아보도록 하겠습니다

코드로 생성하는 방법

stepContribution 을 이용한 방식

@Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
        .tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {

                JobParameters jobParameters = stepContribution.getStepExecution().getJobExecution().getJobParameters();
                jobParameters.getString("name");
                jobParameters.getLong("seq");
                jobParameters.getDate("date");
                jobParameters.getDouble("age");

                System.out.println("step1");
                return RepeatStatus.FINISHED;
            }
        })
                .build();
    }
  • stepContribution 방식은 보면 jobParameters 타입의 객체가 반환 된다

chunkContext 을 이용한 방식

@Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
        .tasklet(new Tasklet() {
            @Override
            public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
                

                Map<String, Object> jobParameters1 = chunkContext.getStepContext().getJobParameters();
                
                System.out.println("step1");
                return RepeatStatus.FINISHED;
            }
        })
                .build();
    }
  • chunkContext 방식은 보면 Map 의 형태로 반환 된다
    • 반환 받는 값은 stepContribution 과 동일하다

❗어플리케이션 실행시 주입 하는 방법 과코드로 생성하는 방법 2가지를 만들어 보았습니다

'Spring Batch' 카테고리의 다른 글

Spring Batch 도메인 Step  (0) 2022.08.23
Spring Batch 도메인 JobExecution  (0) 2022.08.22
Spring Batch 도메인 Joblnstance  (0) 2022.08.19
Spring Batch 도메인 Job  (0) 2022.08.19
Spring Batch 테이블 의미  (0) 2022.08.18