spring batch 5.0

spring boot 3.0에서 spring batch 5.0이 추가되었다. spring batch 5.0 에서 기존에 아래와 같이 사용하던 방법이 deprecated 되었다.

1. 기존

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

@Configuration
@RequiredArgsConstructor
@Slf4j
public class MemberBatchJobConfig {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    private final MemberService memberService;


    @Value("${chunkSize:1000}")
    private int getChunkSize;

    @Bean
    public Job memberJob() {
        return jobBuilderFactory.get("memberJob")
                .start(memberStep())
                .build();
    }

    @Bean
    @JobScope
    public Step memberStep() {
        return this.stepBuilderFactory.get("memberStep")
                .<Member, Member>chunk(getChunkSize)
                .reader(this.memberReader())
                .writer(this.memberWireter())
                .build();
    }

    private ListItemReader<Member> memberReader() {
        return new ListItemReader<>(this.memberService.findAll());
    }

    @Bean
    public ItemWriter<Member> memberWriter() {
        return this::all;
    }

    private void all(final List<? extends Member> list) {
        list.forEach(item -> {
            log.info(item);
        });
    }
}

2. Spring Batch 5.0 에서의 방법

1
2
3
4
5
6
@EnableBatchProcessing
@Configuration
@EnableScheduling
public class Config {
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Configuration
@RequiredArgsConstructor
@Slf4j
public class CustomJobConfig extends DefaultBatchConfiguration {

    private final MemberService memberService;

    @Value("${chunkSize:1000}")
    private int getChunkSize;

    @Bean
    public Job job(final JobRepository jobRepository, final Step sendSmsStackStep) {
        return new JobBuilder("job", jobRepository)
                .start(sendSmsStackStep)
                .build();
    }

    @Bean
    public Step step(final JobRepository jobRepository,
                     final PlatformTransactionManager transactionManager) {
        return new StepBuilder("step", jobRepository)
                .chunk(this.getChunkSize, transactionManager)
                .reader(this.memberReader())
                .writer(this.memberWriter())
                .build();
    }

    private ListItemReader<Member> memberReader() {
        return new ListItemReader<>(this.memberService.getAllMember());
    }

    @Bean
    public ItemWriter<Object> memberWriter() {
        return this::loggingAll;
    }

    private void loggingAll(final Chunk<?> objects) {
        objects.getItems().forEach(item -> log.info(item.toString()));
    }


}

3. 참고

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Component
@RequiredArgsConstructor
public class JobScheduler {

    private final Job job;

    private final JobLauncher jobLauncher;

    @Scheduled(cron = "0 0 9 * * *", zone = "Asia/Seoul")
    public void nine() {
        this.schedulerRun(this.job);
    }


    private void schedulerRun(final Job job) {
        final Map<String, JobParameter<?>> stringJobParameterMap = new SoftHashMap<>();
        stringJobParameterMap.put("time", new JobParameter<>(System.currentTimeMillis(), Long.class));
        final JobParameters jobParameters = new JobParameters(stringJobParameterMap);
        try {
            this.jobLauncher.run(job, jobParameters);
        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException |
                 JobParametersInvalidException | JobRestartException e) {
            e.printStackTrace();
        }
    }
}