008 Step Contribution

강의메모 #

스프링 배치 도메인 이해 - StepContribution #

기본 개념 #

  • 청크 프로세스의 변경 사항을 버퍼링 한 후 StepExecution 상태를 업데이트하는 도메인 객체
  • 청크 커밋 직전에 StepExecution 의 apply 메서드를 호출하여 상태를 업데이트 함
  • ExitStatus 의 기본 종료코드 외 사용자 정의 종료코드를 생성해서 적용 할 수 있음

구조 #

img.png

참고 #

https://devfunny.tistory.com/687

  • apply() 메서드를 호출한 경우 : StepContribution의 변경 사항이 StepExecution에 반영
  • apply() 메서드를 호출하지 않을 경우 : StepExecution에 StepContribution의 변경 사항이 반영안됨

Spring Batch에서는 일반적으로 StepContribution의 변경 사항이 자동으로 StepExecution에 적용된다. 따라서 apply()를 수동으로 호출해 줄 필요는 없다. 일반적으로 Spring Batch의 구현은 내부적으로 Step의 실행 도중 StepContribution 객체를 업데이트하고, Step이 완료될 때 해당 변경 사항을 StepExecution에 자동으로 반영한다.

TaskletStep.java

public RepeatStatus doInTransaction(TransactionStatus status) {
    TransactionSynchronizationManager.registerSynchronization(this);
    RepeatStatus result = RepeatStatus.CONTINUABLE;
    StepContribution contribution = this.stepExecution.createStepContribution();
    TaskletStep.this.chunkListener.beforeChunk(this.chunkContext);
    this.oldVersion = new StepExecution(this.stepExecution.getStepName(), this.stepExecution.getJobExecution());
    this.copy(this.stepExecution, this.oldVersion);

    try {
        try {
            result = TaskletStep.this.tasklet.execute(contribution, this.chunkContext);
            if (result == null) {
                result = RepeatStatus.FINISHED;
            }
        } catch (Exception var17) {
            if (TaskletStep.this.transactionAttribute.rollbackOn(var17)) {
                this.chunkContext.setAttribute("sb_rollback_exception", var17);
                throw var17;
            }
        } finally {
            try {
                this.semaphore.acquire();
                this.locked = true;
            } catch (InterruptedException var15) {
                TaskletStep.logger.error("Thread interrupted while locking for repository update");
                this.stepExecution.setStatus(BatchStatus.STOPPED);
                this.stepExecution.setTerminateOnly();
                Thread.currentThread().interrupt();
            }

            if (TaskletStep.logger.isDebugEnabled()) {
                TaskletStep.logger.debug("Applying contribution: " + contribution);
            }

            this.stepExecution.apply(contribution);
        }
        
        ...
}