본문 바로가기
Spring.io

Spring Batch+quartz 연동

by Andrew's Akashic Records 2023. 3. 31.
728x90

Spring Batch와 Quartz를 연동하려면 먼저 Quartz를 설정하고, Quartz Job을 생성한 다음에 Spring Batch Job을 Quartz Job 내에서 실행하도록 설정해야 합니다. 다음은 Spring Batch와 Quartz를 연동하는 예시 코드입니다.

의존성 추가:
build.gradle 파일에 Quartz와 Spring Batch의 의존성을 추가합니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-batch'
    implementation 'org.springframework:spring-context-support'
    implementation 'org.quartz-scheduler:quartz:2.3.2'
}

 

Quartz 설정:
Quartz 설정을 위한 QuartzConfig.java 파일을 생성하고, SchedulerFactoryBean을 구성합니다.

import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;
import java.util.Properties;

@Configuration
public class QuartzConfig {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
        jobDetailFactoryBean.setJobClass(QuartzJobLauncher.class);
        jobDetailFactoryBean.setDurability(true);
        return jobDetailFactoryBean;
    }

    @Bean
    public Trigger trigger(JobDetail jobDetail) {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10) // 스케줄링 주기 (예: 10초마다)
                .repeatForever();

        return TriggerBuilder.newTrigger()
                .forJob(jobDetail)
                .withSchedule(scheduleBuilder)
                .build();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger trigger, JobDetail jobDetail) throws IOException {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
        schedulerFactoryBean.setJobFactory(springBeanJobFactory());
        schedulerFactoryBean.setJobDetails(jobDetail);
        schedulerFactoryBean.setTriggers(trigger);

        return schedulerFactoryBean;
    }

    @Bean
    public SpringBeanJobFactory springBeanJobFactory() {
        AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    @Bean
    public PropertiesFactoryBean quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean;
    }
}

 

AutoWiringSpringBeanJobFactory.java 파일을 생성하여 Quartz Job이 Spring Bean을 주입 받을 수 있도록 설정합니다.

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutoWiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

	private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
}


Quartz Job 생성:

`QuartzJobLauncher.java` 파일을 생성하여 Spring Batch Job을 실행하는 Quartz Job을 구성합니다.

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.configuration.JobLocator;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;

public class QuartzJobLauncher implements Job {

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private JobLocator jobLocator;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            JobParameters jobParameters = new JobParametersBuilder()
                    .addLong("time", System.currentTimeMillis())
                    .toJobParameters();

            // "myJob"은 Spring Batch Job의 이름입니다.
            jobLauncher.run(jobLocator.getJob("myJob"), jobParameters);
        } catch (Exception e) {
            throw new JobExecutionException(e);
        }
    }
}

 

Spring Batch Job 구성:
예를 들어, 간단한 Spring Batch Job을 작성하고 이를 실행합니다.

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableBatchProcessing
public class BatchConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job myJob(Step myStep) {
        return jobBuilderFactory.get("myJob")
                .start(myStep)
                .build();
    }

    @Bean
    public Step myStep(ItemReader<String> reader, ItemWriter<String> writer) {
        return stepBuilderFactory.get("myStep")
                .<String, String>chunk(1)
                .reader(reader)
                .writer(writer)
                .build();
    }

    @Bean
    public ItemReader<String> reader() {
        List<String> data = Arrays.asList("Hello", "World");
        return new ListItemReader<>(data);
    }

    @Bean
    public ItemWriter<String> writer() {
        return items -> items.forEach(System.out::println);
    }
}


이제 프로젝트를 실행하면, Quartz 스케줄러가 설정된 주기에 따라 Spring Batch Job이 실행됩니다. 이 예제에서는 10초마다 Job이 실행되도록 설정되어 있습니다.

728x90

'Spring.io' 카테고리의 다른 글

Spring Boot+JWT 구현  (0) 2023.04.03
Spring Boot+WebSocket 구현  (0) 2023.03.31
Spring Boot Actuator  (0) 2023.03.23
Spring All Dependency Injection Types  (0) 2021.02.19
Spring Boot Project 만들기  (0) 2021.01.26