1. Spring Batch Step Listener 소개
- Spring Batch에서 Step 실행 과정 중에는 다양한 이벤트가 발생하며, 개발자는 이러한 이벤트에 대해 특정 로직을 수행해야 할 경우가 있습니다.
- 예를 들어, 플랫 파일 작성 시 푸터를 추가하려면 Step이 완료되었을 때 ItemWriter에게 알림을 보내야 합니다.
- Spring Batch는 이러한 요구사항을 충족하기 위해 다양한 Step 범위의 Listener를 제공합니다.
정보
Step Listener는 Step, Tasklet, 또는 Chunk 선언 내에서 listeners 엘리먼트를 통해 적용할 수 있습니다. 기능이 적용되는 레벨에서 리스너를 선언하는 것을 권장합니다.
2. Step Listener 등록 방법
2.1 Java Configuration을 통한 등록
Java Configuration 예시
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.<String, String>chunk(10, transactionManager)
.reader(reader())
.writer(writer())
.listener(chunkListener())
.build();
}
위 예시는 chunk 레벨에서 리스너를 적용하는 방법을 보여줍니다.
2.2 자동 등록
- ItemReader, ItemWriter, 또는 ItemProcessor가 StepListener 인터페이스를 구현하는 경우, Step에 자동으로 등록됩니다.
- 이는 해당 컴포넌트가 Step에 직접 주입된 경우에만 적용됩니다.
- 리스너가 다른 컴포넌트 내부에 중첩되어 있는 경우 에는 명시적으로 등록해야 합니다.
2.3 어노테이션을 통한 등록
- Spring Batch는 어노테이션 기반의 접근 방식도 지원합니다.
- 일반적인 Java 객체의 메서드에 어노테이션을 추가하면 해당하는 StepListener 타입으로 자동 변환됩니다.
3. StepExecutionListener
3.1 개념
- StepExecutionListener는 Step 실행에 대한 가장 일반적인 리스너입니다.
- Step이 시작되기 전과 종료된 후(정상 종료 또는 실패)에 알림을 받을 수 있습니다.
3.2 StepExecutionListener 인터페이스
public interface StepExecutionListener extends StepListener {
void beforeStep(StepExecution stepExecution);
ExitStatus afterStep(StepExecution stepExecution);
}
beforStep
메서드는 Step 실행 전에 호출됩니다.afterStep
메서드는ExitStatus
를 반환하여, Step 완료 시 반환되는 종료 코드를 수정할 수 있는 기회를 제공합니다.
3.3 대응하는 어노테이션
@BeforeStep
: Step 실행 전에 호출됩니다.@AfterStep
: Step 실행 후에 호출됩니다.
4. ChunkListener
4.1 개념
- "Chunk"는 트랜잭션 범위 내에서 처리되는 아이템들을 의미합니다.
- 각 커밋 간격마다 트랜잭션을 커밋하면서 청크를 처리합니다.
- ChunkListener를 사용하여 청크 처리가 시작되기 전이나 성공적으로 완료된 후에 로직을 수행할 수 있습니다.
4.2 ChunkListener 인터페이스
public interface ChunkListener extends StepListener {
void beforeChunk(ChunkContext context);
void afterChunk(ChunkContext context);
void afterChunkError(ChunkContext context);
}
beforeChunk
: 트랜잭션이 시작된 후 ItemReader에서 읽기가 시작되기 전에 호출됩니다.afterChunk
: 청크가 커밋된 후에 호출됩니다(롤백이 발생하면 호출되지 않습니다).afterChunkError
: 청크 처리 중 오류가 발생했을 때 호출됩니다.
4.3 대응하는 어노테이션
@BeforeChunk
@AfterChunk
@AfterChunkError
4.4 ChunkListener 주의사항
- ChunkListener는 체크된 예외를 던지도록 설계되지 않았습니다.
- ChunkListener의 메서드들(beforeChunk, afterChunk, afterChunkError)에서 IOException, SQLException 같은 체크된 예외를 던지면 안 됩니다.
- 오류는 구현체에서 처리해야 하며, 그렇지 않으면 Step이 종료됩니다.
- 리스너에서 예외가 발생해서 전체 배치 처리가 중단되는 것은 바람직하지 않습니다. 따라서 리스너 내부에서 예외를 처리해야 합니다.
5. ItemReadListener
5.1 개념
- ItemReadListener는 읽기 오류가 발생한 레코드를 로깅하여 나중에 처리할 때 유용합니다.
5.2 ItemReadListener 인터페이스
public interface ItemReadListener<T> extends StepListener {
void beforeRead();
void afterRead(T item);
void onReadError(Exception ex);
}
beforeRead
: ItemReader의 각 read 호출 전에 호출됩니다.afterRead
: 성공적인 read 호출 후에 호출되며, 읽은 아이템을 전달받습니다.onReadError
: 읽기 중 오류가 발생했을 때 호출되며, 발생한 예외를 제공합니다.