Spring boot를 사용함으로써 Scheduler 객체를 SchedulerFactory를 통해서 생성하고 직접 시작시켜줘야 하지만 SchedulerFactoryBean을 통해서 자동으로 시작된 상태로 생성할 수 있다.
Quartz 스케줄러 테스트를 위한 JAVA 소스에 대하여 간단히 리뷰하도록 하겠다.
Quartz 개념과 용어에 대해서는 이전 포스팅을 확인하기 바란다.
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: never
#initialize-schema: always
테이블이 생성되지 않았다면 initialize-schema 설정을 always로 하여 자동으로 생성할 수도 있다.
always로 하면 서버가 실행될 때 drop 하고 다시 생성하게 되는 것에 유의하자.
always가 아닌 직접 생성해도 무방하다.
delete from qrtz_fired_triggers;
delete from qrtz_simple_triggers;
delete from qrtz_simprop_triggers;
delete from qrtz_cron_triggers;
delete from qrtz_blob_triggers;
delete from qrtz_triggers;
delete from qrtz_job_details;
delete from qrtz_calendars;
delete from qrtz_paused_trigger_grps;
delete from qrtz_locks;
delete from qrtz_scheduler_state;
drop table qrtz_calendars;
drop table qrtz_fired_triggers;
drop table qrtz_blob_triggers;
drop table qrtz_cron_triggers;
drop table qrtz_simple_triggers;
drop table qrtz_simprop_triggers;
drop table qrtz_triggers;
drop table qrtz_job_details;
drop table qrtz_paused_trigger_grps;
drop table qrtz_locks;
drop table qrtz_scheduler_state;
CREATE TABLE qrtz_job_details
(
SCHED_NAME VARCHAR2(120) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
JOB_CLASS_NAME VARCHAR2(250) NOT NULL,
IS_DURABLE VARCHAR2(1) NOT NULL,
IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE qrtz_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
NEXT_FIRE_TIME NUMBER(19) NULL,
PREV_FIRE_TIME NUMBER(19) NULL,
PRIORITY NUMBER(13) NULL,
TRIGGER_STATE VARCHAR2(16) NOT NULL,
TRIGGER_TYPE VARCHAR2(8) NOT NULL,
START_TIME NUMBER(19) NOT NULL,
END_TIME NUMBER(19) NULL,
CALENDAR_NAME VARCHAR2(200) NULL,
MISFIRE_INSTR NUMBER(2) NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE qrtz_simple_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
REPEAT_COUNT NUMBER(7) NOT NULL,
REPEAT_INTERVAL NUMBER(12) NOT NULL,
TIMES_TRIGGERED NUMBER(10) NOT NULL,
CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_cron_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CRON_EXPRESSION VARCHAR2(120) NOT NULL,
TIME_ZONE_ID VARCHAR2(80),
CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_simprop_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
STR_PROP_1 VARCHAR2(512) NULL,
STR_PROP_2 VARCHAR2(512) NULL,
STR_PROP_3 VARCHAR2(512) NULL,
INT_PROP_1 NUMBER(10) NULL,
INT_PROP_2 NUMBER(10) NULL,
LONG_PROP_1 NUMBER(19) NULL,
LONG_PROP_2 NUMBER(19) NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR2(1) NULL,
BOOL_PROP_2 VARCHAR2(1) NULL,
TIME_ZONE_ID VARCHAR2(80) NULL,
CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_blob_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
BLOB_DATA BLOB NULL,
CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_calendars
(
SCHED_NAME VARCHAR2(120) NOT NULL,
CALENDAR_NAME VARCHAR2(200) NOT NULL,
CALENDAR BLOB NOT NULL,
CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE qrtz_paused_trigger_grps
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE qrtz_fired_triggers
(
SCHED_NAME VARCHAR2(120) NOT NULL,
ENTRY_ID VARCHAR2(140) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
FIRED_TIME NUMBER(19) NOT NULL,
SCHED_TIME NUMBER(19) NOT NULL,
PRIORITY NUMBER(13) NOT NULL,
STATE VARCHAR2(16) NOT NULL,
JOB_NAME VARCHAR2(200) NULL,
JOB_GROUP VARCHAR2(200) NULL,
IS_NONCONCURRENT VARCHAR2(1) NULL,
REQUESTS_RECOVERY VARCHAR2(1) NULL,
CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE qrtz_scheduler_state
(
SCHED_NAME VARCHAR2(120) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
LAST_CHECKIN_TIME NUMBER(19) NOT NULL,
CHECKIN_INTERVAL NUMBER(13) NOT NULL,
CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE qrtz_locks
(
SCHED_NAME VARCHAR2(120) NOT NULL,
LOCK_NAME VARCHAR2(40) NOT NULL,
CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
COMMIT;
spring:
datasource:
hikari:
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
jdbc-url: jdbc:log4jdbc:oracle:thin:@//127.0.0.1:1521/XE
username: DEVLOG
password: devlog
quartz:
auto-startup: true
job-store-type: jdbc
jdbc:
initialize-schema: never
properties:
org:
quartz:
dataSource: #JobStore가 사용할 데이터소스
devlogQuartzDataSource:
provider: hikaricp #default c3p0 커넥션 풀
URL: jdbc:log4jdbc:oracle:thin:@//127.0.0.1:1521/XE
driver: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
user: DEVLOG
password: devlog
scheduler:
instanceId: AUTO #AUTO인 경우 인스턴스 ID를 임의로 생성
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
dataSource: devlogQuartzDataSource
useProperties: false
tablePrefix: QRTZ_ # DB에 생성된 Quartz 테이블에 주어진 접두사를 지정
misfireThreshold: 60000 #스케줄러가 실패한 것으로 간주되기 전에 다음 실행 시간을 전달하는 트리거를 허용하는 시간
isClustered: false # 클러스터링 기능을 사용여부
threadPool:
threadCount: 3
Quartz의 dataSource를 직접 선언하였기 때문에 JAVA Configuration 파일에서는 별도로 선언해 주지 않아도 된다.
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import com.devlog.quartz.cmm.JobsListener;
import com.devlog.quartz.cmm.TriggersListener;
@Configuration
public class QuartzConfiguration {
@Autowired
private TriggersListener triggersListener;
@Autowired
private JobsListener jobsListener;
@Value("${spring.quartz.auto-startup}")
private boolean quartzAutoStartup;
/**
* @param quartzProperties
* @param applicationContext
* @return
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(QuartzProperties quartzProperties, ApplicationContext applicationContext) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setApplicationContext(applicationContext);
Properties properties = new Properties();
properties.putAll(quartzProperties.getProperties());
schedulerFactoryBean.setGlobalTriggerListeners(triggersListener);
schedulerFactoryBean.setGlobalJobListeners(jobsListener);
schedulerFactoryBean.setOverwriteExistingJobs(true);
schedulerFactoryBean.setQuartzProperties(properties);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true); //서버 shutdown시 실행 중인 Job 종료를 기다릴지 여부
schedulerFactoryBean.setSchedulerName("DevLogQuartz");
schedulerFactoryBean.setAutoStartup(quartzAutoStartup); // 스케줄러 초기화 후 자동실행 여부 / default : true
return schedulerFactoryBean;
}
}
스프링에서는 4.1부터 Quartz 스케줄러 생성 작업을 쉽게 해주는 SchedulerFactoryBean을 제공한다.
Quartz 2.1.4 이상이면 호환 가능하다.
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.JobListener;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class JobsListener implements JobListener {
@Override
public String getName() {
return "globalJob";
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
JobKey jobKey = context.getJobDetail().getKey();
log.info("Job 수행 되기 전 jobkey : {}", jobKey);
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
JobKey jobKey = context.getJobDetail().getKey();
log.info("Job 중단 jobkey : {}", jobKey);
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
JobKey jobKey = context.getJobDetail().getKey();
log.info("Job 수행 완료 후 jobkey : {}", jobKey);
}
}
Config파일에서 SchedulerFactoryBean에 등록해 준다.
Job 실행 전후로 이벤트를 받을 수 있다.
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Trigger;
import org.quartz.TriggerListener;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class TriggersListener implements TriggerListener {
@Override
public String getName() {
return "globalTrigger";
}
@Override
public void triggerFired(Trigger trigger, JobExecutionContext context) {
JobKey jobKey = trigger.getJobKey();
log.info("Trigger 실행 {} : jobkey : {}", trigger.getStartTime(), jobKey);
}
/**
* Trigger 중단여부를 확인하는 메소드
*
* 결과가 true이면 JobListener JobExcutionVetoed(Job중단) 실행
*/
@Override
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
return false;
}
@Override
public void triggerMisfired(Trigger trigger) {
JobKey jobKey = trigger.getJobKey();
log.info("triggerMisfired at {} : jobkey : {}", trigger.getStartTime(), jobKey);
}
/**
* Trigger 완료 후 실행
*/
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
JobKey jobKey = trigger.getJobKey();
log.info("Trigger 성공 {} : jobkey : {}", trigger.getStartTime(), jobKey);
}
}
Config파일에서 SchedulerFactoryBean에 등록해 준다.
Trigger 실행 전후로 이벤트를 받을 수 있다.
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import lombok.extern.slf4j.Slf4j;
/**
* Schedule Job 실행 Class
*
*/
@Slf4j
public class CronJob extends QuartzJobBean {
/**
* 배치 실행
*/
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
/*구현부*/
log.error("=============================Quartz Cron Execute====================");
log.error("JobName : {}",context.getJobDetail().getKey().getName());
log.error("JobGroup : {}",context.getJobDetail().getKey().getGroup());
log.error("===================================================================");
}
}
QuartzJobBean을 상속받으면 executeInternal 메서드를 구현해야 한다.
스케줄러에 의해 Job클래스가 호출되었을 때 executeInternal 메서드가 실행된다.
import java.text.ParseException;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
public class QuartzUtils {
private QuartzUtils() {
}
/**
* Job 생성
* @param quartzDto - Quartz Job 정보
* @param jobClass - Job 생성할 Class
* @param context - ApplicationContext
* @return JobDetail
*/
public static JobDetail createJob(QuartzDto quartzDto, Class<? extends Job> jobClass, ApplicationContext context) {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
factoryBean.setDurability(false);
factoryBean.setApplicationContext(context);
factoryBean.setName(quartzDto.getJobName());
factoryBean.setGroup(quartzDto.getJobGroup());
factoryBean.setDescription(quartzDto.getDesc());
if (quartzDto.getJobDataMap() != null) {
factoryBean.setJobDataMap(quartzDto.getJobDataMap());
}
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
/**
* Trigger 생성(Cron)
* @param quartzDto - Quartz Job 정보
* @return Trigger
*/
public static Trigger createTrigger(QuartzDto quartzDto) {
String cronExpression = quartzDto.getCronExpression();
if (!CronExpression.isValidExpression(cronExpression)) {
throw new IllegalArgumentException("Provided expression " + cronExpression + " is not a valid cron expression");
} else {
return createCronTrigger(quartzDto);
}
}
/**
* CronTrigger 생성
* @param quartzDto - Quartz Job 정보
* @return Trigger
*/
private static Trigger createCronTrigger(QuartzDto quartzDto) {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setName(quartzDto.getJobName().concat("Trigger"));
factoryBean.setGroup(quartzDto.getJobGroup());
factoryBean.setCronExpression(quartzDto.getCronExpression());
factoryBean.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING); //MsiFired Trigger 무시
try {
factoryBean.afterPropertiesSet();
} catch (ParseException e) {
e.printStackTrace();
}
return factoryBean.getObject();
}
}
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import com.devlog.quartz.cmm.QuartzDto;
import com.devlog.quartz.cmm.QuartzUtils;
import com.devlog.quartz.job.CronJob;
@Service
public class QuartzManagerService {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
public boolean addJob(QuartzDto quartzDto) {
JobDetail jobDetail;
Trigger trigger;
try {
jobDetail = QuartzUtils.createJob(quartzDto, CronJob.class, applicationContext);
trigger = QuartzUtils.createTrigger(quartzDto);
schedulerFactoryBean.getScheduler().scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean deleteJob(QuartzDto quartzDto) {
boolean result;
try {
result = schedulerFactoryBean.getScheduler().deleteJob(JobKey.jobKey(quartzDto.getJobName(), quartzDto.getJobGroup()));
} catch (Exception e) {
result = false;
}
return result;
}
}
QuartzUtils를 사용하여 add, delete Job 메서드를 구현.
import java.util.Map;
import org.quartz.SchedulerException;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.devlog.quartz.cmm.QuartzDto;
import com.devlog.quartz.service.QuartzManagerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequestMapping("/Quartz")
@Controller
@RequiredArgsConstructor
public class QuartzTestController {
private final QuartzManagerService quartzManagerService;
@RequestMapping("/AddJob")
public ResponseEntity<Void> addJob(@RequestParam Map<String, Object> paramMap) throws SchedulerException {
//http://127.0.0.1:28081/Quartz/AddJob?jobName=testJob&jobGroup=testJobGroup&jobDesc=test&cronExpr=0 * * * * ?
log.error(paramMap.toString());
QuartzDto quartzDto = new QuartzDto();
quartzDto.setJobName(paramMap.get("jobName").toString());
quartzDto.setJobGroup(paramMap.get("jobGroup").toString());
quartzDto.setDesc(paramMap.get("jobDesc").toString());
quartzDto.setCronExpression(paramMap.get("cronExpr").toString());
quartzManagerService.addJob(quartzDto);
return ResponseEntity.ok().build();
}
@RequestMapping("/DeleteJob")
public ResponseEntity<Void> deleteJob(@RequestParam Map<String, Object> paramMap) {
//http://127.0.0.1:28081/Quartz/DeleteJob?jobName=testJob&jobGroup=testJobGroup
log.error(paramMap.toString());
QuartzDto quartzDto = new QuartzDto();
quartzDto.setJobName(paramMap.get("jobName").toString());
quartzDto.setJobGroup(paramMap.get("jobGroup").toString());
quartzManagerService.deleteJob(quartzDto);
return ResponseEntity.ok().build();
}
}
Quartz 테스트를 위해 Get방식으로 데이터를 전송받는 Controller를 만들었다.
어떤 프로그램에 Quartz에 설정된 Job이 30개가 있다고 가정하자.
근데 그중 하나의 Job을 수정해야 한다.
간단한 문제일까?
하나의 서버에 Quartz(Scheduler)와 Job(Batch)이 존재하게 되면 배포는 스케줄러의 중단을 의미한다.
어떠한 고민을 해야 할까?
이게 정답이 아닐 수는 있겠지만 내가 한 고민이 누군가에게 도움이 됐으면 하는 바람으로 생각해야 하는 부분에 대해 작성해 보겠다.
[JAVA] Quartz - 개념 (40) | 2024.07.28 |
---|
댓글 영역