아래 강의를 보고 정리한 내용입니다.
[우아한테크세미나] 190926 우아한스프링배치 by 우아한형제들 이동욱님 https://youtu.be/_nkJkWVH-mo
- JobParameter
- Spring Batch는 외부에서 파라미터를 주입받아 Batch 컴포넌트에서 사용 할 수 있다.
- 사용법 : @Value("#{jobParameters[파라미터명]}") 타입 이름
- @JobScope
- Step에서 사용할 수 있고, Job이 실행되는 시점에 Bean이 생성된다.
- 사용 예
- @JobScope라고 선언해줘야 호출한 곳에서 넘겨진 파라미터를 받을 수 있다.
- 컴파일 에러 방지를 위해 우선은 null값을 넘겨준다.
@Bean
public Job scopeJob() {
return jobBuilderFactory.get("scopeJob")
.start(scopeStep1(null))
.next(scopeStep2())
.build();
}
@Bean
@JobScope
public Step scopeStep1(@Value("#{jobParameters[requestDate]}") String requestDate) {
return stepBuilderFactory.get("scopeStep1")
.tasklet((contribution, chunkContext) -> {
log.info(">>> ");
return RepeatStatus.FINISHED;
})
.build();
}
- @StepScope
- Tasklet / Reader / Processor / Writer에서 사용할 수 있다.
@Bean
pulbic Step scopeStep2() {
return stepBuilderFactory.get("scopeStep2")
.tasklet(scopeStep2Tasklet(null))
.build();
}
@Bean
@StepScope
public Tasklet scopeStep2Tasklet(@Value("#{jobParameters[requestDate]}") String requestDate) {
return (contribution, chunkContext) -> {
log.info(">>>");
return RepeatStatus.FINISHED;
}
}
- Type
- Spring Batch의 JobParameter는 Long / String / Double / Date 타입들을 지원한다.
- Enum / LocalDate / LocalDateTime은 지원하지 않는다.
- 그렇다면?
- @Value의 특성을 이용하면 String을 매번 LocalDateTime으로 변경하지 않아도 된다. (아래 코드 참고)
- setter메소드에 @Value를 선언 문자열로 받은뒤 원하는 타입으로 세팅
- @Value의 특성을 이용하면 String을 매번 LocalDateTime으로 변경하지 않아도 된다. (아래 코드 참고)
- 그렇다면?
@Slf4j
@Getter
@NoArgsConstructor
public class CreateDateJobParameter {
private LocalDate localDate;
@Value("#{jobParameters[createDate]}")
public void setCreateDate(String createDate) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
this.createDate = LocalDate.parse(createDate, formatter);
}
}
@JobScope로 설정해놨기 때문에 Job이 실행될 때 Bean이 실행된다. 그러면 job실행되는 시점에 jobParameter Bean이 생성되서 값이 세팅된 다음에 CreateDateJobParameter에 Injection이 된다.
public class JObParameterBatchConfiguration {
private final CreateDateJobParameter jobParameter;
@Bean(BATCH_NAME + "jobParameter")
@JobScope
public CreateDateJobParameter jobParameter() {
return new CreateDateJobParameter():
}
}
그 다음부터는 아래와 같이 사용하면 된다.jobParameter.getCreateDate()만 호출하면 된다.
@Bean(name = BATCH_NAME + "_reader")
@StepScope
public JpaPagingItemReader<Product> reader() {
Map<String, Object> params = new HashMap<>();
params.put("createDate", jobParameter.getCreateDate()); // 어디에서나 LocalDate을 가져올 수 있음
return new JpaPagingItemReaderBuilder<Product>()
.name(BATCH_NAME + "_reader")
.entityManagerFactory(entityManagerFactory)
.pageSize(chunkSize)
.queryString("SELECT p FROM Product p WHERE p.createDate = :createDate")
.parameterValues(params)
.build();
}
- @JobScope, @StepScope의 특징(Late Binding)을 활용해보기
- @JobScope나 @StepScope가 선언된 Bean의 경우에는 Job이나 Step이 실행될 때 Bean이 생성되는 특징을 가진다. (일반 Spring처럼 애플리케이션이 로딩될 때 Bean이 생성되는 것이 아니라)
- 그 뜻은 애플리케이션 실행 후에도 동적으로 reader / processor / writer bean 생성이 가능하다는 뜻
- 예를 들아보자
- 정산하는 시스템에서 ERP 연동이 2-30개가 되는데 하는 일이 비슷
- 주문데이터 긁어와서 어디에 보내는 것~ 파라미터가 주문이냐 매출이냐 광고냐 그리고 읽어와야 될 테이블 이 값만 다르고 다른 건 전부 동일
- 그럴 때 마다 같은 클래스를 계속 생성할 수 없으니 LateBinding을 이용해서 파라미터로 주문으로 던지면 주문 테이블에서 읽어오는 리더로 바꿔서 배치를 돌리고, 광고면 광고 테이블에서 읽어오는 리더로 바꿔서 배치를 돌리는 것이다.
- 예를 들아보자
private StimpleStepBuilder<EaiEntity, EaiItem> readerAndProcessor(String dealCode, String txDateStr) {
EaiReaderParameterDato parameterDto = createParameter(dealCode, txDateStr);
EaiTaskletType readerProcessorType = EaiDatailType.findTaskletType(dealCode);
EaiReaderFactory readerCreator = readerProcessorType.getReaderCreator();
return stepBuilderFactory.get(stepName)
.<~>chunk(chunkSize)
.reader(readerCreator.create(chunkSize, emf, parameterDto))
.processor(eaiProcessor);
}
'스프링 > Spring Batch' 카테고리의 다른 글
Spring Cloud Data Flow & Spring Batch 사용 (실패), docker-compose 파일 (0) | 2023.03.22 |
---|---|
Spring Batch를 사용하며 맞닥뜨린 상황 기록 02 (0) | 2023.02.28 |
Spring Batch를 사용하며 맞닥뜨린 상황 기록 01 (0) | 2023.02.14 |
스프링배치 핵심 개념 체크를 위한 Questions (메타데이터 테이블, skip&retry, chunk oriented, cursor & paging 등) (0) | 2022.11.16 |
Spring Batch 에 대한 이해 (0) | 2021.02.08 |