처음부터 끝까지 독립적으로 실행할 수 있는 고유하며, 순서가 지정된 여러 Step의 목록
Job이름과 Parameter를 받아들여 Job을 실행시키는 역할이다.
종류 | 설명 |
---|---|
CommandLineJobRunner | script를 이용하거나 cli에서 직접 Job을 실행할 때 사용 |
JobRegisteryBackgroundJobRunner | Spring내에서 Job을 실행한다면, 실행 가능한 Job을 가지고 있는 JobRegistry를 생성한다. JobRegistry를 생성하는데 사용하는 Runner이다. |
JobLauncherCOmmandLineRunner | Spring Boot는 ApplicationContext에 정의된 Job타입의 모든 빈을 기동 시에 실행 |
Job의 논리적 실행을 나타내고, 한 번 성공적으로 완료되면 다시 실행시킬 수 없다.
org.springframework.batch.core.JobInstance
가 생성BATCH_JOB_INSTANCE
에 저장BATCH_JOB_INSTANCE
와 BATCH_JOB_EXECUTION_PARAMS
테이블을 사용Job 실행의 실제 시도를 의미한다.
BATCH_JOB_EXECUTION
테이블에 저장BATCH_JOB_EXECUTION_CONTEXT
테이블에 저장p.96-98
JobInstance를 식별하는 값이다. 동일한 식별 파라미터로 동일한 잡을 두 번 이상 실행할 수 없다.
# key: executionDate
# value: 2020/12/27
# value data type: date
java -jar demo.jar executionDate(date)=2020/12/27
# name은 식별자에서 제외
java -jar demo.jar executionDate(date)=2020/12/27 -name=Michael
BATCH_JOB_EXECUTION_PARAMS
테이블에서 확인-
를 사용하면, 식별자에서 제외된다.// ChunkContext
@Bean
public Tasklet helloWorldTasklet() {
return (contribution, chunkContext) -> {
String name (String) chunkContext.getStepContext()
.getJobParameters()
.get("name");
System.out.println(String.foramt("Hello, %s!", name));
return RepeatStatus.FINISHED;
};
}
// Late Binding
@Bean
public Step step1() {
return this.stepBuilderFactory.get("step1")
.tasklet(helloWorldTasklet(null))
.build();
}
@Bean
public Tasklet helloWorldTasklet(
@Value("#{jobParameters['name']}") String name) {
return (contribution, chunkContext) -> {
String name (String) chunkContext.getStepContext()
.getJobParameters()
.get("name");
System.out.println(String.foramt("Hello, %s!", name));
return RepeatStatus.FINISHED;
};
}
// @StepScope
@StepScope
@Bean
public Tasklet helloWorldTasklet(
@Value("#{jobParameters['name']}") String name) {
return (contribution, chunkContext) -> {
String name (String) chunkContext.getStepContext()
.getJobParameters()
.get("name");
System.out.println(String.foramt("Hello, %s!", name));
return RepeatStatus.FINISHED;
};
}
값이 예상한대로 유효한지 확인한다.
// JobParametersValidator
// JobPArametersInvalidException이 발생하지 않으면 유효성 검증은 통과
public class ParameterValidator implements JobParametersValidator {
@Override
public void validate(JobParameters parameters) throws JobParametersInvalidException {
String fileName = parameters.getString("fileName");
if (!StringUtils.hasText(fileName)) {
throw new JobPArametersInvalidExcetion("fileName parameter is missing!");
} else if (!StringUtils.endsWithIgnoreCase(fileName, "csv")) {
throw new JobParametersInvalidException("fileName parameter does not use the csv file extension");
}
}
}
// DefaultJobParametersValidator
// 필수 파라미터가 누락없이 전달됐는지 확인하는 유효성 검증기
// fileName과 name 외 다른 파라미터 변수가 전달되면 검증 실패
// optionalKey가 구성되지 않으면, 필수키만 전달하면 검증 통과
@Bean
public JobParametersValidator validator() {
DefaultJobParametersValidator validator = new DefaultJobParametersValidator();
validator.setRequiredKeys(new String[] { "fileName" });
validator.setOptionalKeys(new String[] { "name" });
return validator;
}
// CompositeJobParametersValidator
// 두 개의 유효성 검증기
@Bean
public CompositeJobParametersValidator validator() {
CompositeJobParametersValidator validator = new CompositeJobParametersValidator();
DefaultJobParametersValidator defaultJobParametersValidator = new DefaultJobParametersValidator(
new String[] { "fileName" },
new String[] { "name" });
defaultJobParametersValidator.afterPropertiesSet();
validator.setValidators(
Arrays.asList(new ParameterValidator(), defaultJobParametersValidator);
return validator;
}
@Bean
public Job job() {
return this.jobBuilderFactory.get("basicJob")
.start(step1())
.validator(validator())
.build();
}
Incrementer: 파라미터를 고유하게 생성할 수 있는 인터페이스
// RunIdIncrementer
// 프레임웤에서 제공하는 구현체
// Validator에 run.id 값을 추가해야함
@Bean
public CompoisteJobParameterValidator validator() {
...
DefaultJobParametersValidator defaultJobParametersValidator = new DefaultJobParametersValidator(
new String[] { "fileName" },
new String[] { "name", "run.id" });
...
}
@Bean
public Job job() {
return this.jobBuilderFactory.get("basicJob")
.start(step1())
.validator(validator())
.incrementer(new RunIdIncrementer())
.build();
}
}
// DailyJobTimestamper
// Custom Incrementer
// currentDate를 유효성 검증기에 추가해야 함
public class DailyJobTimestamper implements JobParametersIncrementer {
@Override
public JobParameters getNext(JobParameters parameters) {
return new JobParametersBuilder(parameters)
.addDate("currentDate", new Date())
.toJobParameters();
}
}
@Bean
public CompoisteJobParameterValidator validator() {
...
DefaultJobParametersValidator defaultJobParametersValidator = new DefaultJobParametersValidator(
new String[] { "fileName" },
new String[] { "name", "currentDate" });
...
}
@Bean
public Job job() {
return this.jobBuilderFactory.get("basicJob")
.start(step1())
.validator(validator())
.incrementer(new DailtJobTimestamper())
.build();
}
}