[java] Quartz Scheduler에서 작업 간의 트랜잭션 관리하기

Quartz Scheduler는 Java 기반의 오픈 소스 라이브러리로, 작업 스케줄링을 쉽게 관리할 수 있는 기능을 제공합니다. 그러나 여러 작업을 동시에 실행하면서 트랜잭션 관리가 필요한 경우가 있을 수 있습니다. 이번 포스트에서는 Quartz Scheduler에서 작업 간의 트랜잭션을 관리하는 방법에 대해 알아보겠습니다.

1. Job 클래스에 @Transactional 어노테이션 추가하기

Quartz Scheduler에서 트랜잭션을 관리하기 위해서는 각 작업을 수행하는 Job 클래스에 @Transactional 어노테이션을 추가해야 합니다. 이 어노테이션은 Spring Framework의 트랜잭션 관리를 지원하며, 작업 수행 시 자동으로 트랜잭션을 시작하고, 성공적으로 작업을 완료한 경우에는 커밋하고, 예외가 발생한 경우에는 롤백합니다.

import org.springframework.transaction.annotation.Transactional;
import org.quartz.*;

@Transactional
public class MyJob implements Job {

    public void execute(JobExecutionContext context) {
        // 작업 수행 로직
    }
}

2. JobFactory 클래스에서 TransactionalJobBean 생성하기

Quartz Scheduler는 각 Job 인스턴스를 생성하는 JobFactory를 사용합니다. 따라서 트랜잭션을 관리하기 위해서는 JobFactory 클래스를 사용하여 TransactionalJobBean을 생성해주어야 합니다.

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.AdaptableJobFactory;

public class MyJobFactory extends AdaptableJobFactory {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object job = super.createJobInstance(bundle);
        applicationContext.getAutowireCapableBeanFactory().autowireBean(job);
        return new TransactionalJobBean((Job) job);
    }
}

3. TransactionalJobBean 클래스 생성하기

TransactionalJobBean은 Spring의 트랜잭션 관리를 위해 Job 인터페이스를 구현한 클래스입니다. 이 클래스에서는 작업 수행 시 트랜잭션을 시작하고, 커밋 또는 롤백하는 로직을 구현합니다.

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TransactionalJobBean implements Job {

    private Job targetJob;
    private PlatformTransactionManager transactionManager;

    public TransactionalJobBean(Job targetJob, PlatformTransactionManager transactionManager) {
        this.targetJob = targetJob;
        this.transactionManager = transactionManager;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());

        try {
            targetJob.execute(context);
            transactionManager.commit(txStatus);
        } catch (Exception e) {
            transactionManager.rollback(txStatus);
            throw new JobExecutionException(e);
        }
    }
}

4. Spring 설정 파일에 Quartz Scheduler 관련 빈 등록하기

마지막으로 Spring의 설정 파일에 Quartz Scheduler와 관련된 빈들을 등록해야 합니다. 아래 예시는 Quartz Scheduler를 설정하는 XML 파일의 내용입니다.

<bean id="quartzJobFactory" class="com.example.MyJobFactory">
    <property name="applicationContext" ref="applicationContext" />
</bean>

<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobFactory" ref="quartzJobFactory" />
    <!-- 다른 설정들 추가 -->
</bean>

위의 설정 파일에서 quartzJobFactory 빈이 MyJobFactory 클래스를 참조하고 있음을 볼 수 있습니다. 이를 통해 MyJobFactory 클래스를 사용하여 트랜잭션을 관리하는 TransactionalJobBean을 생성할 수 있습니다.

결론

Quartz Scheduler에서 작업 간의 트랜잭션을 관리하기 위해서는 @Transactional 어노테이션과 TransactionalJobBean 클래스를 사용하여 트랜잭션을 시작, 커밋 및 롤백해야 합니다. 이를 통해 여러 작업을 안전하게 실행하면서 트랜잭션 관리를 할 수 있습니다.

참고 자료: