들어가기 스프링 부트는 CommandLineRunner, ApplicationRunner 라는 두가지 메커니즘을 이요해 실행 시 로직을 수행한다. 이 두 인터페이스는 ApplicationContext 가 리프레시(refresh) 되고, 애플리케이션이 코드를 실행할 준비가 된 이후에 호출되는 하나의 메서드를 가지고 있다. 스프링 부트를 스프링 배치가 함께 사용할때는 JobLauncherCommandLineRunner 라는 CommandLineRunner 가 사용된다. JobLauncherCommandLineRunner 스프링 배치의 JobLauncher 를 사용해 잡을 실행한다. 스프링부트가 ApplicationContext 내에 구성된 모든 CommandLineRunner 를 실행할때, 클래스 패스에 s..
잡의 종료 상태 스프링 배치의 잡은 종료 상태를 가진다. 잡 실행시 갖게되는 JobInstance 는 성공적으로 완료되면 두번 이상 실행될 수 없다. 이는 잡 이름과 파라미터로 식별된다. 만일 사용자가 프로그래밍 방식으로 잡을 종료한다면, 잡의 종료 상태를 알고 그에 따라 분기할 수 있어야한다. 잡의 종료 상태는 3가지이다. 1) Completed (완료) 2) Fail (실패) 3) Stopped (중지) 스프링 배치가 JobRepository 에 저장할 BatchStatus를 판별할때 스쳅의 ExitStatus 를 평가한다. ExitStatus 는 스텝, 청크, 잡에서 반환될 수 있다. BatchStatus 는 JobExecution 또는 StepExecution 내에 보관되고, JobReposito..
상황 스프링 배치가 진행중이다. 진행 도중에 오류가 발생했고, 실패한 시점부터 처리를 다시 시작해야한다. 이 경우에 스프링 배치는 실패한 시점을 어떻게 알아낼 수 있을까? 실패시마다, 사용자가 실행 상태를 재설정하는 일은 매우 번거롭고 어렵다. 스프링 배치가 이를 대신해준다. JobExecution 우리는 이미 JobExecution 에 대해 배웠다. https://devfunny.tistory.com/476?category=820618 [스프링배치] 잡의 실행 (JobLauncher, JobInstance, JobExecution, JobParameters) 잡의 실행 잡의 실행은 잡 러너 (Job Runner) 에서 시작된다. 잡 러너는 잡 이름과 여러 파라미터를 받아, 잡을 실행시킨다. 스프링 배치..
JobExecutionListener 해당 리스너를 통해 잡 리스너를 적용시킬 수 있다. JobExecutionListener는 2개의 메소드를 제공한다. beforeJob : 잡 생명주기에서 가장 먼저 실행된다. afterJob : 잡 생명주기에서 가장 나중에 실행된다. : 잡의 완료 상태에 관계 없이 호출된다. : 잡의 종료 상태에 따라 분기 처리를 할 수 있다. 구현방법 beforeJob, afterJob 메서드 모두 JobExecution 을 파라미터로 전달받아 실행된다. 여기서 JobExecution란, 스프링 배치 잡의 실제 실행을 의미한다. 잡을 구동할 때마다 매번 새로운 JobExecution 을 얻게된다. https://devfunny.tistory.com/476 [스프링배치] 잡의 실행..
ChunkContext public class HelloWorld implements Tasklet { private static final String HELLO_WORLD = "Hello, %s"; @Override public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception { /** * StepContext 의 getStepExecutionContext 메소드가 존재 * : 잡의 ExecutionContext 의 현재 상태를 나타내는 Map를 반환한다. * 현재 값에 접근할 수 있지만, 반환된 Map 을 변경하더라도 실제 내용이 바뀌지 않는다. * 따라서 실제 Exec..
JobRepository 스프링 배치가 제공하는 여러 데이터베이스 테이블을 사용하여 배치 메타데이터를 저장한다. 총 6개의 테이블이 존재하는데, 각 테이블 정보에 대해 알아보자. BATCH_JOB_INSTANCE 테이블 잡을 식별하는 고유 정보가 포함된 잡 파라미터로 잡을 처음 실행하면 단일 JobInstance 레코드가 테이블에 등록된다. 필드 설명 JOB_EXECUTION_ID 테이블의 기본 키 VERSION oplimistic locking 에 사용되는 레코드 버전 JOB_NAME 실행된 잡의 이름 JOB_KEY 잡 이름과 잡 파라미터의 해시 값으로, JobInstance 를 고유하게 식별하는 데 사용되는 값 BATCH_JOB_EXECUTION 테이블 배치 잡의 실제 실행 기록을 나타낸다. 잡이 실..
잡의 실행 잡의 실행은 잡 러너 (Job Runner) 에서 시작된다. 잡 러너는 잡 이름과 여러 파라미터를 받아, 잡을 실행시킨다. 스프링 배치는 2가지 잡 러너를 제공한다. 1) CommandLineJobRunner 스크립트를 이용하거나 명령행에서 직접 잡을 실행할때 사용한다. 2) JobRegistryBackgroundJobRunner 스프링을 부트스트랩해서 기동한 자바 프로세스 내에서 Quartz 나 JMX 후크와 같은 스케줄러를 사용하여 잡을 실행할때 사용한다. JobRegistry 를 생성하는데 사용하는데, 이 JobRegistry는 스프링이 부트스트랩될 때 실행 가능한 잡을 가지고 있다. 3) JobLauncherCommandLineRunner CommandRunner 구현체는 별도의 구성이..
스프링부트 프로젝트 예제 package com.example.springbatch; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; i..
잡 (Job) 상태를 수집하고 이전 상태에서 다음 상태로 전환된다. 스텝 (Step) 스프링 배치에서 가장 일반적으로 상태를 보여주는 단위이다. 각 스텝은 잡을 구성하는 독립된 작업의 단위이다. 스텝에는 Tasklet, Chunk 기반으로 2가지가 있다. 1) Tasklet package org.springframework.batch.core.step.tasklet; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.repeat.RepeatStatus; import org.spri..
예제파일 DTO 1) Product.java package dto.Product; import lombok.Getter; import lombok.Setter; import java.util.Optional; public class Product { private int idx; private String productName; private int ordCnt; private int totalCnt; private Optional person; public int getIdx() { return idx; } public String getProductName() { return productName; } public int getOrdCnt() { return ordCnt; } public int ge..
참고 DTO package dto.Product; import java.util.Optional; public class Person { private int idx; private String personName; private Optional job; public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public Optional getJob() { return job; ..
forEach List numbers = Arrays.asList(2, 3, 5, 6); numbers.stream() .map(x -> x + 3) .filter(x -> x % 2 == 0) .limit(3) .forEach(System.out::println); /* 디버깅 x 결과 출력 */ 스트림의 파이프라인 연산을 디버깅하자. forEach 로 스트림 결과를 출력하거나 로깅할 수 있다. 하지만 forEach를 호출하게되면, 호출 순간에 전체 스트림이 소비된다. peek 스트림 연산 peek 을 활용하자. 호출 순간 전체 스트림을 소비하는 forEach 에 비해 peek은 실제로 스트림의 요소를 소비하지는 않는다. peek 은 자신이 확인한 요소를 파이프라인의 다음 연산으로 그대로 전달하고, 각..