Skip to content

Commit 9e554d3

Browse files
committed
QuartzSchedulerService for Dynamic Scheduling with DB Persistence.
1 parent ba70379 commit 9e554d3

File tree

8 files changed

+96
-33
lines changed

8 files changed

+96
-33
lines changed

pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,12 @@
137137
<groupId>org.springframework.boot</groupId>
138138
<artifactId>spring-boot-starter-validation</artifactId>
139139
</dependency>
140-
<dependency>
141-
<groupId>org.springframework.boot</groupId>
142-
<artifactId>spring-boot-devtools</artifactId>
143-
<scope>runtime</scope>
144-
<optional>true</optional>
145-
</dependency>
140+
<!-- <dependency>-->
141+
<!-- <groupId>org.springframework.boot</groupId>-->
142+
<!-- <artifactId>spring-boot-devtools</artifactId>-->
143+
<!-- <scope>runtime</scope>-->
144+
<!-- <optional>true</optional>-->
145+
<!-- </dependency>-->
146146
<dependency>
147147
<groupId>org.springframework.boot</groupId>
148148
<artifactId>spring-boot-starter-logging</artifactId>

src/main/java/org/wsd/app/config/QuartzConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
import lombok.extern.log4j.Log4j2;
2626
import org.springframework.context.annotation.Configuration;
2727

28+
import javax.sql.DataSource;
29+
2830
@Log4j2
2931
@Configuration
3032
public class QuartzConfig {
33+
3134
}

src/main/java/org/wsd/app/controller/QuartzController.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ public List<JobTimer> getRunningTimers() {
3333
return quartzSchedulerService.getRunningTimers();
3434
}
3535

36+
@DeleteMapping(path = "/deleteJob")
37+
public boolean deleteJob(@RequestParam("jobId") String jobId) {
38+
return quartzSchedulerService.deleteJob(jobId);
39+
}
40+
41+
@PostMapping(path = "/pauseJob")
42+
public boolean pauseJob(@RequestParam("jobId") String jobId) {
43+
return quartzSchedulerService.pauseJob(jobId);
44+
}
45+
46+
@PostMapping(path = "/resumeJob")
47+
public boolean resumeJob(@RequestParam("jobId") String jobId) {
48+
return quartzSchedulerService.resumeJob(jobId);
49+
}
50+
3651
@GetMapping(path = "/getRunningTimer")
3752
public JobTimer getRunningTimer(@RequestParam("timerId") String timerId, @RequestParam("group") String group) {
3853
return quartzSchedulerService.getRunningTimer(timerId, group);

src/main/java/org/wsd/app/quartz/JobTimer.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import lombok.Data;
44

55
import java.io.Serializable;
6-
import java.util.UUID;
76

87
@Data
98
public class JobTimer implements Serializable {

src/main/java/org/wsd/app/quartz/QuartzSchedulerService.java

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import jakarta.annotation.PreDestroy;
55
import lombok.RequiredArgsConstructor;
66
import lombok.extern.log4j.Log4j2;
7+
import org.apache.commons.lang3.StringUtils;
78
import org.quartz.*;
89
import org.quartz.impl.matchers.GroupMatcher;
910
import org.springframework.stereotype.Service;
@@ -31,9 +32,9 @@ public void onInit() {
3132
public void scheduleJob(Class<? extends Job> clazz, JobTimer jobTimer) {
3233
final JobDetail job = buildJob(clazz, jobTimer);
3334
final Trigger trigger = buildTrigger(jobTimer);
34-
3535
try {
3636
scheduler.scheduleJob(job, trigger);
37+
log.info("Quartz job has been scheduled with id : " + jobTimer.getJobId());
3738
} catch (SchedulerException e) {
3839
log.error(e.getMessage(), e);
3940
throw new RuntimeException(e);
@@ -53,10 +54,11 @@ public JobTimer getRunningTimer(String timerId, String group) {
5354

5455

5556
public void updateTimer(String timerId, String group, JobTimer jobTimer) {
56-
final JobKey jobKey = new JobKey(timerId, group);
57+
final JobKey jobKey = new JobKey(timerId);
5758
try {
5859
final JobDetail job = scheduler.getJobDetail(jobKey);
5960
job.getJobDataMap().put(jobKey.getName(), jobTimer);
61+
scheduler.addJob(job, true, true);
6062
} catch (SchedulerException e) {
6163
log.error(e.getMessage(), e);
6264
}
@@ -84,29 +86,39 @@ public List<JobTimer> getRunningTimers() {
8486
}
8587

8688
private Trigger buildTrigger(JobTimer jobTimer) {
87-
SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule()
88-
.withIntervalInMilliseconds(jobTimer.getRepeatIntervalMs());
89-
90-
if (jobTimer.isRunForever()) {
91-
builder = builder.repeatForever();
89+
if (StringUtils.isNotEmpty(jobTimer.getCronExpression())) {
90+
return TriggerBuilder.newTrigger()
91+
.withIdentity(jobTimer.getJobId())
92+
.withSchedule(CronScheduleBuilder.cronSchedule(jobTimer.getCronExpression()))
93+
.startAt(new Date(System.currentTimeMillis() + jobTimer.getInitialOffsetMs()))
94+
.build();
9295
} else {
93-
builder = builder.withRepeatCount(jobTimer.getTotalFireCount() - 1);
96+
SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule()
97+
.withIntervalInMilliseconds(jobTimer.getRepeatIntervalMs());
98+
99+
if (jobTimer.isRunForever()) {
100+
builder = builder.repeatForever();
101+
} else {
102+
builder = builder.withRepeatCount(jobTimer.getTotalFireCount() - 1);
103+
}
104+
105+
return TriggerBuilder
106+
.newTrigger()
107+
.withIdentity(jobTimer.getJobId())
108+
// .withIdentity(jobTimer.getJobId(), jobTimer.getGroupName())
109+
.withSchedule(builder)
110+
.startAt(new Date(System.currentTimeMillis() + jobTimer.getInitialOffsetMs()))
111+
.build();
94112
}
95-
96-
return TriggerBuilder
97-
.newTrigger()
98-
.withIdentity(jobTimer.getJobId(), jobTimer.getGroupName())
99-
.withSchedule(builder)
100-
.startAt(new Date(System.currentTimeMillis() + jobTimer.getInitialOffsetMs()))
101-
.build();
102113
}
103114

104115
private JobDetail buildJob(Class<? extends Job> clazz, JobTimer jobTimer) {
105116
final JobDataMap dataMap = new JobDataMap();
106117
dataMap.put(jobTimer.getJobId(), jobTimer);
107118
return JobBuilder
108119
.newJob(clazz)
109-
.withIdentity(jobTimer.getJobId(), jobTimer.getGroupName())
120+
.withIdentity(jobTimer.getJobId())
121+
//.withIdentity(jobTimer.getJobId(), jobTimer.getGroupName())
110122
.setJobData(dataMap)
111123
.build();
112124
}
@@ -121,4 +133,33 @@ public void onDestroy() {
121133
}
122134
}
123135

136+
public boolean deleteJob(String jobId) {
137+
try {
138+
boolean deletedJob = scheduler.deleteJob(new JobKey(jobId));
139+
log.info("Quartz job has been deleted with id : " + jobId);
140+
return deletedJob;
141+
} catch (SchedulerException e) {
142+
return false;
143+
}
144+
}
145+
146+
public boolean pauseJob(String jobId) {
147+
try {
148+
scheduler.pauseJob(new JobKey(jobId));
149+
log.info("Quartz job has been pause with id : " + jobId);
150+
return true;
151+
} catch (SchedulerException e) {
152+
return false;
153+
}
154+
}
155+
156+
public boolean resumeJob(String jobId) {
157+
try {
158+
log.info("Quartz job has been resumed with id : " + jobId);
159+
scheduler.resumeJob(new JobKey(jobId));
160+
return true;
161+
} catch (SchedulerException e) {
162+
return false;
163+
}
164+
}
124165
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package org.wsd.app.quartz;
22

3+
import lombok.extern.log4j.Log4j2;
34
import org.quartz.Job;
45
import org.quartz.JobDataMap;
56
import org.quartz.JobExecutionContext;
67
import org.quartz.JobExecutionException;
78

89
import java.util.Date;
910

11+
@Log4j2
1012
public class SampleJob implements Job {
1113
@Override
1214
public void execute(JobExecutionContext context) throws JobExecutionException {
1315
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
14-
JobTimer jobTimer = (JobTimer) dataMap.get("SampleJob");
15-
System.out.println("Executing job..." + new Date() + " " + jobTimer);
16+
JobTimer jobTimer = (JobTimer) dataMap.get("1");
17+
log.info("Remaining Job Count : " + jobTimer.getRemainingCount());
1618
}
1719
}

src/main/java/org/wsd/app/quartz/listener/SimpleTriggerListener.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.wsd.app.quartz.listener;
22

33
import lombok.RequiredArgsConstructor;
4+
import org.apache.commons.lang3.StringUtils;
45
import org.quartz.*;
56
import org.springframework.stereotype.Service;
67
import org.wsd.app.quartz.JobTimer;
@@ -23,7 +24,9 @@ public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContex
2324
JobTimer jobTimer = (JobTimer) dataMap.get(timerId);
2425
if (!jobTimer.isRunForever()) {
2526
int remainingCount = jobTimer.getRemainingCount();
26-
jobTimer.setRemainingCount(remainingCount - 1);
27+
if (!StringUtils.isNotEmpty(jobTimer.getCronExpression())) {
28+
jobTimer.setRemainingCount(remainingCount - 1);
29+
}
2730
}
2831
this.quartzSchedulerService.updateTimer(timerId, null, jobTimer);
2932
}

src/main/resources/application.properties

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ spring.jpa.properties.hibernate.javax.cache.provider=org.ehcache.jsr107.EhcacheC
77
spring.jpa.properties.hibernate.generate_statistics=false
88

99
# Quartz Configuration
10-
#spring.quartz.job-store-type=jdbc
11-
#spring.quartz.jdbc.initialize-schema=always
12-
#spring.quartz.properties.org.quartz.jobStore.useProperties=false
13-
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
14-
#spring.quartz.properties.org.quartz.jobStore.isClustered=true
15-
#spring.quartz.auto-startup=true
16-
#spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
10+
spring.quartz.job-store-type=jdbc
11+
spring.quartz.jdbc.initialize-schema=never
12+
spring.quartz.properties.org.quartz.jobStore.useProperties=false
13+
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
14+
spring.quartz.properties.org.quartz.jobStore.isClustered=true
15+
spring.quartz.auto-startup=true
16+
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
1717

1818
# Log Configuration
1919
logging.file.name=logs/app.log

0 commit comments

Comments
 (0)