이전 포스팅에서 Job의 작업 실행횟수를 실행하기 위해 jobDataMap의 executeCount 변수를 활용한 적이 있다.
@Component
public class QuartzBatchJob implements org.quartz.Job {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private BeanUtil beanUtil;
private int executeCount = 0;
@SneakyThrows
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDetail jobDetail = context.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
if(jobDataMap.containsKey("executeCount")){
executeCount = jobDataMap.getInt("executeCount");
}
jobDataMap.put("executeCount", ++executeCount);
Job job = (Job) beanUtil.getBean((String) jobDataMap.get(QuartzService.JOB_NAME));
JobParameters jobParameters = new JobParametersBuilder()
.addDate("curDate", new Date())
.toJobParameters();
jobLauncher.run(job,jobParameters);
}
}
JobExcutionContext가 무엇일까? 아니 그 전에 JobExcution은 무엇일까?
JobLauncher를 통해 배치 잡이 실행된다.
배치 잡이 실행되면 JobInstance가 생성된다.
JobInstance는 잡의 논리적 실행을 나타낸다. Job의 이름, Job에게 전달되어 실행시에 사용되는 식별 파라미터
해당 두 가지로 식별된다.
JobExecution은 무엇일까?
잡 실행의 실제 시도를 의미한다. 잡이 처음부터 끝까지 단번에 실행 완료되었다면 JobInstance와 JobExecution은 단 하나씩만 존재할 것이다.
첫 번째 Job 실행 후 오류 상태로 종료가 되었다면, 이전과 동일한 파라미터로 해당 JobInstance를 실행하려고 시도할 때마다 새로운 JobExecution이 생성된다.
JobExecutionContext는 하나의 Job에 해당하는 Context이다. 그렇기에 Job을 구성하는 step들 간에는 공유가 가능하다.
그렇다면, 현재 나는 Job이 딱 한번만 실행하길 원하는 상황이었다.
그런데 execute를 통해 호출이 끝나면 그 Job은 그냥 끝난 것이다.
다시 호출이 되면 다시 시작하는 것이니 다시 또 executeCount가 초기값으로 시작될 것이다.
해당 문제를 고민하다가 찾은 결과는 생각보다 허무했다.
그냥 말 그대로 해당 executeCount, 더 나아가 Job이 끝나도 해당 정보가 저장되게 하면 되는 것이었다.(stateful?)
@PersistJobDataAfterExecution을 붙여줌으로써, 해당 문제를 해결했다.
@PersistJobDataAfterExecution // jobDataMap 데이터 수정 이후 다음 실행에도 데이터 반영
@Component
public class QuartzBatchJob implements org.quartz.Job {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private BeanUtil beanUtil;
private int executeCount = 0;
@SneakyThrows
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDetail jobDetail = context.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
if(jobDataMap.containsKey("executeCount")){
executeCount = jobDataMap.getInt("executeCount");
}
jobDataMap.put("executeCount", ++executeCount);
Job job = (Job) beanUtil.getBean((String) jobDataMap.get(QuartzService.JOB_NAME));
JobParameters jobParameters = new JobParametersBuilder()
.addDate("curDate", new Date())
.toJobParameters();
jobLauncher.run(job,jobParameters);
}
}
'스프링 정리' 카테고리의 다른 글
왜 생성자 주입이 @Autowired(필드 주입)보다 좋을까? (0) | 2023.11.07 |
---|---|
테스트코드에서의 @Transactional (0) | 2023.10.30 |
Spring Security & JWT(Json Web Token) 활용 예제 (0) | 2023.03.28 |
Spring Batch & Quartz 활용해보기 (0) | 2023.03.24 |
Spring Batch 간단하게 활용해보기(스프링 배치 5.0) (2) | 2023.03.24 |