[Spring] Batch RunIdIncrementer 적용 불가 이슈

박성우·2023년 8월 28일
0

Spring

목록 보기
9/10

Spring Batch를 사용하면서 Job을 같은 JobParameter로 여러 번 실행하고자 RunIdIncrementer를 적용했는데, 무슨 이유 때문인지 첫 실행 이후로는 계속해서 중복된 JobParameter라는 에러가 발생했다.

실행 환경은 다음과 같았다.

protected JobExecution launchJob(Job job, JobParameters jobParameters) throws Exception {
    JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
    jobLauncherTestUtils.setJob(job);
    jobLauncherTestUtils.setJobLauncher(jobLauncher);
    jobLauncherTestUtils.setJobRepository(jobRepository);
    return jobLauncherTestUtils.launchJob(jobParameters);
}

만든 Job을 테스트하기 위해 JobLauncherTestUtils를 통해 Job을 실행시키고자 하였고,

JobParameters jobParameters = new JobParametersBuilder()
                .addString("today", "2023-08-28")
                .toJobParameters();
JobExecution jobExecution = launchJob(myJob, jobParameters);

Job을 실행시키기 위한 JobParameter에는 today 문자열과 날짜를 인자로 받았는데 만약 같은 날짜에 두 번 이상 실행될 경우 중복될 수 있는 경우였다.

따라서 다음과 같이 Job에 RunIdIncrementer를 적용시켜 JobParameter의 중복을 피하고자 하였다.

    @Bean
    public Job myJob(
            JobRepository jobRepository,
            JobParameterValidator validator,
            Step myStep
    ) {
        return new JobBuilder("myJob", jobRepository)
                .incrementer(new RunIdIncrementer())
                .validator(validator)
                .start(myStep)
                .build();
    }

하지만 테스트를 실행했을 때 RunIdIncrementer는 적용되지 않고 있었고, 그 이유는 의외로 간단했다.

JobLauncherTestUtils의 launchJob 메소드는 직접적으로 JobLauncher 클래스의 run() 메소드를 호출해서 Job을 실행하고 있었다.

하지만 커맨드 라인을 이용한 Job 동작 과정을 보면 Bean으로 등록된 JobLauncherApplicationRunner로부터 Job을 실행시키기 위한 세팅이 시작되는데,

그 과정에서 결과적으로 JobLauncher의 run()을 호출하기 전에 getNextJobParameters()를 호출하고 있고 해당 메서드에서 getJobParametersIncrementer() 호출을 통해 Incrementer의 유무를 파악하고 JobParameter의 중복을 막아주고 있었던 것이였다.

Incrementer가 존재할 경우, Repository에 접근하여 배치 작업에 대한 정보를 얻을 수 있는 JobExplorer를 이용하여 기존의 JobParameter의 정보와 함께 새로운 JobParameter를 생성해준다.

결국, 테스트를 위한 JobLauncherTestUtils 클래스를 통해 Job을 실행하면 JobLauncher를 직접적으로 불러다가 Job을 실행하게 되는 것이고 앞선 RunIdIncrementer를 적용시켜줄 수 있는 로직을 생략하고 Job을 실행시키고 있었던 것이였다.

해당 문제를 해결하기 위해

JobParameters jobParameters = new JobParametersBuilder(jobExplorer)
        .addString("today", "2023-08-28")
        .getNextJobParameters(myJob)
        .toJobParameters();
JobExecution jobExecution = launchJob(myJob, jobParameters);

JobParameter를 생성할 때 위의 getJobParametersIncrementer() 메소드처럼 JobExplorer를 이용하여 RunIdIncrementer가 적용될 수 있도록 바꿔주어서 해결하였다.

profile
Backend Developer

0개의 댓글