반응형
스프링 배치 완벽 가이드 내용 정리입니다
3장. 예제 잡 어플리케이션은 스킵했습니다
http://www.yes24.com/Product/Goods/99422216
1. 잡 파라미터
- 앞서 배치 잡이 실행되면 JobInstnace가 생기고, 생겨난 JobInstance는 JobName + JobParameters로 식별된다고 했습니다
- 이를 통해 동일하게 식별되는 JobInstance(같은 JobName이면서 같은 JobParameter로 실행된)가 정상적으로 성공된 JobExecution을 가진다면 해당 JobInstance는 다시 실행할 수 없습니다
- 위에서 정의한 예제를 두번이상 실행하게 되면 아래와 같은 로그를 보실수 있습니다
// teminal Step already complete or not restartable, so no action to execute: StepExecution
- 위에서 정의한 예제를 두번이상 실행하게 되면 아래와 같은 로그를 보실수 있습니다
- 스프링 부트의 JobLauncherCommandLineRunner를 기준으로 파라미터 전달 방법을 소개하겠습니다
- key=value 쌍으로 전달한다
- 사용자가 배치 잡에게 파라미터를 전달하면 잡 러너는 JobParameters 인스턴스를 생성하는데, 해당 인스턴스는 잡이 전달받는 모든 파라미터의 컨테이너 역할을 한다
- JobPrameters 인스턴스
- java.util.Map<String, JobParameters> 객체의 래퍼
- 스프링 배치는 파라미터의 타입을 변환하는 기능을 제공하며, 변환된 타입에 맞는 JobParameter의 접근자를 제공한다
- 지원하는 타입
- String
- Double
- Long
- java.util.Date
- LocalDate, LocalTime, LocalDateTime이 없기 때문에 String을 변환하는 방식으로 사용해야한다
- 잡 파라미터에 접근하기 :: ChunkContext
- ChunkContext: execute 메서드에는 두개의 파라미터가 존재
- StepContribution: 아직 커밋되지 않은 현재 트랜잭션에 대한 정보(쓰기 수, 읽기 수등)
- ChunkContext: 실행 시점의 잡 상태를 제공, Tasklet 내에서는 처리 중인 청크와 관련된 정보 보유
- ChunkContext에는 JobParameters가 포함된 org.springframework.batch.core.scope.context.StepContext의 참조가 있다
- 예제코드
// ChunkContextJobParamterBatch.class @RequiredArgsConstructor @Configuration public class ChunkContextJobParameterBatch { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean public Job chunkContextJobParameterJob() { return this.jobBuilderFactory.get("chunkContextJobParamterJob") .start(chunkContextJobParameterStep()) .build(); } @Bean public Step chunkContextJobParameterStep() { return this.stepBuilderFactory.get("chunkContextJobParameterStep") .tasklet(((contribution, chunkContext) -> { String name = (String) chunkContext.getStepContext().getJobParameters().get("name"); System.out.printf("Hello, %s!%n", name); return RepeatStatus.FINISHED; })) .build(); } }
- getJobParameters()를 호출하는 방식으로 잡 파라미터를 가져오면 Map<String, Object>가 반환된다
- 위 예제처럼 타입 캐스팅이 필요하다
- ChunkContext: execute 메서드에는 두개의 파라미터가 존재
- 잡 파라미터에 접근하기 :: Late Binding
- 주입하기 가장 쉬운 방식
- 스프링 구성을 사용해 주입, 부트스트랩시 바인딩하는 것이 제일 좋다
- 예제코드
// LateBindingJobParameterBatch.class @RequiredArgsConstructor @Configuration public class LateBindingJobParameterBatch { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean("lateBindingJobParameterBatchJob") public Job job() { return this.jobBuilderFactory.get("lateBindingJobParameterBatchJob") .start(step(null)) .build(); } @Bean("lateBindingJobParameterBatchStep") @JobScope public Step step(@Value("#{jobParameters['name']}") String name) { return this.stepBuilderFactory.get("lateBindingJobParameterBatchStep") .tasklet(((contribution, chunkContext) -> { System.out.printf("Hello, %s!%n", name); return RepeatStatus.FINISHED; })) .build(); } }
- 스프링 EL(Expression Language)을 사용해 값을 전달한다
- LateBinding으로 구성될 빈은 StepScope나 JobScope를 반드시 가져야한다
- StepScope: 스텝의 실행범위에 들어갈 때까지 빈 생성을 지연 시킴
- JobScope: 잡의 실행범위에 들어갈 때까지 빈 생성을 지연 시킴
- 잡 파라미터 유효성 검증하기
- 소프트웨어 외부에서 입력을 받아들일 때마다 그 값이 예상대로 유효한지 확인하는 것이 좋다
- org.springframework.batch.core.JobParametersValidator 인터페이스를 구현하고 해당 구현체를 잡 내에 구성하면 된다
- JobParametersInvalidException의 발생유무로 valid를 통과시킨다
- 이미 존재하는 DefaultJobParametersValidator를 이용해 requiredKeys와 optionalKeys라는 선택적인 의존성을 주입할 수 도 있다
- 커스텀 검증 예제코드
// JobParameterValidator.java public class JobParameterValidator implements JobParametersValidator { @Override public void validate(JobParameters parameters) throws JobParametersInvalidException { String fileName = Objects.requireNonNull(parameters).getString("fileName"); if (StringUtils.hasText(fileName)) { throw new JobParametersInvalidException("fileName parameter is missing"); } else if(!StringUtils.endsWithIgnoreCase(fileName, "csv")) { throw new JobParametersInvalidException("fileName parameter does not use the csv file extension"); } } }
- JobParametersInvalidException이 발생하지 않는다면 유효성 검증을 통과했다고 판단한다
- DefaultJobParametersValidator
- 필수 파라미터가 누락없이 전달됐는지 확인하는 유효성 검증기 ( SpringBatch 기본 제공 )
- requiredKeys: 필수 파라미터 목록
- optionalKeys: 필수가 아닌 파라미터 목록
- 예제코드
// HelloWorldBatchWithValidator.java @RequiredArgsConstructor @Configuration public class HelloWorldBatchWithValidator { private static final String JOB_NAME = "helloWorldBatchWithValidatorJob"; private static final String STEP_NAME = "helloWorldBatchWithValidatorStep"; private static final String VALIDATOR_NAME = "helloWorldBatchValidator"; private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean(name = VALIDATOR_NAME) public JobParametersValidator validator() { DefaultJobParametersValidator validator = new DefaultJobParametersValidator(); validator.setRequiredKeys(new String[]{"fileName"}); validator.setOptionalKeys(new String[]{"name"}); return validator; } @Bean(name = JOB_NAME) public Job helloWorldBatchWithValidatorJob() { return this.jobBuilderFactory.get(JOB_NAME) .validator(validator()) .start(helloWorldBatchWithValidatorStep(null, null)) .build(); } @Bean @JobScope public Step helloWorldBatchWithValidatorStep(@Value("#{jobParameters['name']}") String name, @Value("#{jobParameters['fileName']}") String fileName) { return this.stepBuilderFactory.get(STEP_NAME) .tasklet((contribution, chunkContext) -> { System.out.println("Hello, " + name); System.out.println("fileName= " + fileName); return RepeatStatus.FINISHED; }) .build(); } }
- 결과( 필수파라미터인 fileName을 안넣었을 경우 )
- --job.name=helloWorldBatchWithValidatorJob name=joojimin version=5
- "The JobParameters do not contain required keys: [fileName]" 오류가 뜬다
- CompositeJobParametersValidator
- 원하는 두 개의 유효성 검증기를 사용할 수 있도록 변경된 잡 구성
- 파라미터로 제공되는 두 개의 유효성 검증기를 전부 통과해야 Job이 실행된다
- 잡 파라미터 증가시키기
- 주어진 식별 파라미터 집합(JobParameters)으로 같은 잡은 단 한번만 실행시킬 수 있다
- 이를 피하는 간단한 방법은 JobParametersIncrementer를 사용하는 것이다
- org.springframework.batch.core.JobParametersIncrementer
- 잡에서 사용할 파라미터를 고유하게 생성할 수 있도록 스프링 배치가 제공하는 인터페이스
- 매 실행 시에 타임 스탬프를 추가할 수도 있다
- 스프링 배치는 기본적인 구현체를 제공하며 해당 구현체는 run.id인 long 타입 파라미터의 값을 증가시킨다
- 예제코드
// JobParametersIncrementerBatch.java @RequiredArgsConstructor @Configuration public class JobParametersIncrementerBatch { private static final String JOB_NAME = "jobParametersIncrementerBatchJob"; private static final String STEP_NAME = "jobParametersIncrementerBatchStep"; private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean(JOB_NAME) public Job jobParametersIncrementerBatchJob() { return this.jobBuilderFactory.get(JOB_NAME) .start(jobParametersIncrementerBatchStep()) .incrementer(new RunIdIncrementer()) .build(); } @Bean(STEP_NAME) public Step jobParametersIncrementerBatchStep() { return this.stepBuilderFactory.get(STEP_NAME) .tasklet(((contribution, chunkContext) -> { return RepeatStatus.FINISHED; })) .build(); } }
- 결과
- Job: [SimpleJob: [name=jobParametersIncrementerBatchJob]] launched with the following parameters: [{run.id=1}]
- 파라미터는 jobParametersIncrementerBatchJob, jobName만 주고 실행시킨 결과이다
- job이 실행될 때 run.id가 자동으로 들어간 것을 확인할 수 있다
- 추가적으로 유효성 검증기를 사용한다면 RunIdIncrementer를 도입하면서 자동으로 추가되는 파라미터(run.id)의 검증도 추가해줘야한다 ( optional 혹은 required )
- 커스텀한 JobParametersIncrementer를 사용하고 싶으면 그냥 JobParametersIncrementer를 구현하여 getNext 메서드를 구현하면 된다
728x90
반응형
'Study > 스프링배치 완벽 가이드' 카테고리의 다른 글
Day 6. ExecutionContext (0) | 2021.12.26 |
---|---|
Day 5. 잡 리스너 이해하기 (0) | 2021.11.26 |
Day 3. 잡과 스텝 이해하기 (0) | 2021.11.06 |
Day 2. 스프링 배치 (0) | 2021.11.05 |
Day 1. 배치와 스프링 (0) | 2021.11.01 |