티스토리 뷰

spring batch 에서 Step 라이프사이클을 활용해 step 이 실행되기전 선작업이 필요한 경우 2가지 방법이 있다.

StepExecutionListener 인터페이스를 구현하는 방법과 @BeforeStep 애노테이션을 이용해 선언적으로 명시하는 방법이다.

 

- StepExecutionListener 인터페이스를 구현하는 방식(인터페이스의 추상메서드들을 기본으로 구현해주는 스켈레톤 클래스인 StepExecutionListenerSupport 를 상속받았다.)

class SampleTasklet : Tasklet, StepExecutionListenerSupport() {
    override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus? {
        println("hello tasklet")
        return RepeatStatus.FINISHED
    }

    override fun beforeStep(stepExecution: StepExecution) {
        println("hello class before")
    }
}

- @BeforeStep 애노테이션을 이용하는 방식

class SampleTasklet : Tasklet {
    override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus? {
        println("hello tasklet")
        return RepeatStatus.FINISHED
    }

    @BeforeStep
    fun before(stepExecution: StepExecution) {
        println("hello annotation before")
    }
}

두가지 방식중 선호하는 방식을 사용하면되는데 애노테이션을 이용할 경우 아래처럼 tasklet 만 등록해서는 before() 메서드가 정상적으로 호출되지 않는다.

@Bean                                                 
fun sampleStep(sampleTasklet: SampleTasklet): Step =  
    stepBuilderFactory["sampleStep"]                  
        .tasklet(sampleTasklet)                                             
        .build()                                      

이때 이를 해결하는 방법은 2가지가 있다.

1. 애노테이션 방식을 포기하고 StepExecutionListener 를 구현한다

2. listener 에도 등록해준다

 

1번은 이미 위에서 살펴본 방식이므로 자세히 설명하지 않는다. 2번도 특별할건 없는데 아래와 같이 listener 에도 등록해주면 된다.

@Bean                                                
fun sampleStep(sampleTasklet: SampleTasklet): Step = 
    stepBuilderFactory["sampleStep"]                 
        .tasklet(sampleTasklet)                      
        .listener(sampleTasklet)                     
        .build()                                     

 

인터페이스를 구현할때는 동작을 하고, 애노테이션 방식에선 동작하지 않는 이유는 무엇일까? 일단 beforeStep 이 동작하려면 listener 에 등록이 되어야한다. 그럼 애노테이션은 등록이 안되고 인터페이스 구현일때만 등록이 되는 이유는 무엇일까? 현재 스프링 코드는 아래처럼 인스턴스를 확인하여 인터페이스를 구현했을때만 자동으로 listener 를 등록하게 하고있기 때문이다.

public void setTasklet(Tasklet tasklet) {                               
	this.tasklet = tasklet;                                             
	if (tasklet instanceof StepExecutionListener) {                     
		registerStepExecutionListener((StepExecutionListener) tasklet); 
	}                                                                   
}                                                                       

애노테이션 방식을 이용할 경우 저 if 문에서 false 가 나오기 때문에 listener 에 등록되지 않는다. 이게 버그인지 스펙인지는 아직 모르겠으나 @BeforeStep 이 의도한대로 동작하지 않는다면 위와 같이 해결할 수 있다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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 26 27 28
29 30 31
글 보관함