Skip to content

Package: QuartzTriggerDriver

QuartzTriggerDriver

nameinstructionbranchcomplexitylinemethod
createCronJobTrigger(Trigger)
M: 43 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 13 C: 0
0%
M: 1 C: 0
0%
createIntervalJobTrigger(Trigger)
M: 40 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
createQuartzTrigger(KapuaId, KapuaId, KapuaId, JobDataMap)
M: 40 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 13 C: 0
0%
M: 1 C: 0
0%
createQuartzTriggerWithSchedule(Trigger, ScheduleBuilder)
M: 106 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 26 C: 0
0%
M: 1 C: 0
0%
deleteTrigger(Trigger)
M: 21 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
getJobDetail()
M: 33 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
getScheduler()
M: 5 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
initQuarztScheduler()
M: 65 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 20 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others
3: *
4: * This program and the accompanying materials are made
5: * available under the terms of the Eclipse Public License 2.0
6: * which is available at https://www.eclipse.org/legal/epl-2.0/
7: *
8: * SPDX-License-Identifier: EPL-2.0
9: *
10: * Contributors:
11: * Eurotech - initial API and implementation
12: *******************************************************************************/
13: package org.eclipse.kapua.service.scheduler.quartz.driver;
14:
15: import com.google.common.base.Strings;
16: import org.eclipse.kapua.KapuaIllegalNullArgumentException;
17: import org.eclipse.kapua.commons.model.id.KapuaEid;
18: import org.eclipse.kapua.model.id.KapuaId;
19: import org.eclipse.kapua.model.type.ObjectTypeConverter;
20: import org.eclipse.kapua.model.type.ObjectValueConverter;
21: import org.eclipse.kapua.service.job.Job;
22: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.CannotAddQuartzJobException;
23: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.CannotScheduleJobException;
24: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.CannotUnscheduleJobException;
25: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.QuartzTriggerDriverException;
26: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.SchedulerNotAvailableException;
27: import org.eclipse.kapua.service.scheduler.quartz.driver.exception.TriggerNeverFiresException;
28: import org.eclipse.kapua.service.scheduler.quartz.job.KapuaJobLauncher;
29: import org.eclipse.kapua.service.scheduler.trigger.Trigger;
30: import org.eclipse.kapua.service.scheduler.trigger.definition.TriggerProperty;
31: import org.quartz.CronScheduleBuilder;
32: import org.quartz.JobBuilder;
33: import org.quartz.JobDataMap;
34: import org.quartz.JobDetail;
35: import org.quartz.JobKey;
36: import org.quartz.ScheduleBuilder;
37: import org.quartz.Scheduler;
38: import org.quartz.SchedulerException;
39: import org.quartz.SchedulerFactory;
40: import org.quartz.SimpleScheduleBuilder;
41: import org.quartz.TriggerBuilder;
42: import org.quartz.TriggerKey;
43: import org.quartz.impl.StdSchedulerFactory;
44: import org.slf4j.Logger;
45: import org.slf4j.LoggerFactory;
46:
47: import javax.validation.constraints.NotNull;
48: import java.util.Date;
49: import java.util.TimeZone;
50:
51: /**
52: * Utility class to crate Quartz {@link org.quartz.Trigger}s.
53: *
54: * @since 1.1.0
55: */
56: public class QuartzTriggerDriver {
57:
58: private static final Logger LOG = LoggerFactory.getLogger(QuartzTriggerDriver.class);
59:
60: private static Scheduler scheduler;
61:
62: private QuartzTriggerDriver() {
63: }
64:
65: /**
66: * Creates a Quartz {@link org.quartz.Trigger} that starts now.
67: *
68: * @param scopeId The {@link Job#getScopeId()} to start.
69: * @param jobId The {@link Job#getId()} to start
70: * @param uniqueId A unique {@link KapuaId} to associate with the Quartz {@link org.quartz.Trigger}.
71: * @param triggerDataMap The {@link JobDataMap} with properties for the Quartz {@link org.quartz.Trigger}
72: * @since 1.1.0
73: */
74: public static void createQuartzTrigger(@NotNull KapuaId scopeId, @NotNull KapuaId jobId, @NotNull KapuaId uniqueId, @NotNull JobDataMap triggerDataMap) throws QuartzTriggerDriverException {
75: JobDetail kapuaJobLauncherJobDetail = getJobDetail();
76:
77: // Quartz Trigger data map definition
78: TriggerKey triggerKey = TriggerKey.triggerKey(jobId.toCompactId().concat("-").concat(uniqueId.toCompactId()), scopeId.toCompactId());
79:
80: // Quartz Trigger definition
81: TriggerBuilder<org.quartz.Trigger> triggerBuilder = TriggerBuilder.newTrigger()
82: .forJob(kapuaJobLauncherJobDetail)
83: .withIdentity(triggerKey)
84: .usingJobData(triggerDataMap)
85: .startNow();
86:
87: org.quartz.Trigger quarztTrigger = triggerBuilder.build();
88: try {
89: getScheduler().scheduleJob(quarztTrigger);
90: } catch (SchedulerException se) {
91: throw new CannotScheduleJobException(se, kapuaJobLauncherJobDetail, triggerKey, triggerDataMap);
92: }
93: }
94:
95: public static void createIntervalJobTrigger(@NotNull Trigger trigger) throws KapuaIllegalNullArgumentException, QuartzTriggerDriverException {
96: Integer interval = null;
97:
98:• for (TriggerProperty tp : trigger.getTriggerProperties()) {
99:• if ("interval".equals(tp.getName())) {
100: interval = (Integer) ObjectValueConverter.fromString(tp.getPropertyValue(), Integer.class);
101: break;
102: }
103: }
104:
105:• if (interval == null) {
106: throw new KapuaIllegalNullArgumentException("interval");
107: }
108:
109: createQuartzTriggerWithSchedule(
110: trigger,
111: SimpleScheduleBuilder.repeatSecondlyForever(interval)
112: .withMisfireHandlingInstructionFireNow() // This option force a misfired trigger to be always fired
113: );
114: }
115:
116:
117: public static void createCronJobTrigger(@NotNull Trigger trigger) throws KapuaIllegalNullArgumentException, QuartzTriggerDriverException {
118: String cron = null;
119:
120:• for (TriggerProperty tp : trigger.getTriggerProperties()) {
121:• if ("cronExpression".equals(tp.getName())) {
122: cron = (String) ObjectValueConverter.fromString(tp.getPropertyValue(), String.class);
123: break;
124: }
125: }
126:
127:• if (Strings.isNullOrEmpty(cron)) {
128: throw new KapuaIllegalNullArgumentException("cronExpression");
129: }
130:
131: createQuartzTriggerWithSchedule(
132: trigger,
133: CronScheduleBuilder.cronSchedule(cron)
134: .withMisfireHandlingInstructionFireAndProceed() // This option force a misfired trigger to be always fired
135: .inTimeZone(TimeZone.getTimeZone("UTC"))
136: );
137: }
138:
139: public static void deleteTrigger(@NotNull Trigger trigger) throws CannotUnscheduleJobException {
140: TriggerKey triggerKey = TriggerKey.triggerKey(trigger.getId().toCompactId(), trigger.getScopeId().toCompactId());
141:
142: try {
143: getScheduler().unscheduleJob(triggerKey);
144: } catch (SchedulerException | SchedulerNotAvailableException se) {
145: throw new CannotUnscheduleJobException(se, triggerKey);
146: }
147: }
148:
149: //
150: // Private methods
151: //
152:
153: private static void createQuartzTriggerWithSchedule(Trigger trigger, ScheduleBuilder<?> scheduleBuilder) throws QuartzTriggerDriverException {
154: JobDetail kapuaJobLauncherJobDetail = getJobDetail();
155:
156: //
157: // Quartz Trigger data map definition
158: TriggerKey triggerKey = TriggerKey.triggerKey(trigger.getId().toCompactId(), trigger.getScopeId().toCompactId());
159:
160: JobDataMap triggerDataMap = new JobDataMap();
161: try {
162:• for (TriggerProperty tp : trigger.getTriggerProperties()) {
163:• if (KapuaId.class.getName().equals(tp.getPropertyType())) {
164: triggerDataMap.put(tp.getName(), KapuaEid.parseCompactId(tp.getPropertyValue()));
165: } else {
166: triggerDataMap.put(tp.getName(), ObjectValueConverter.fromString(tp.getPropertyValue(), ObjectTypeConverter.fromString(tp.getPropertyType())));
167: }
168: }
169: } catch (ClassNotFoundException cnfe) {
170: throw new RuntimeException(cnfe);
171: }
172:
173: //
174: // Quartz Trigger definition
175: TriggerBuilder<org.quartz.Trigger> triggerBuilder = TriggerBuilder.newTrigger()
176: .forJob(kapuaJobLauncherJobDetail)
177: .withIdentity(triggerKey)
178: .usingJobData(triggerDataMap)
179: .startAt(trigger.getStartsOn())
180: .endAt(trigger.getEndsOn());
181:
182: triggerBuilder.withSchedule(scheduleBuilder);
183:
184: org.quartz.Trigger quartzTrigger = triggerBuilder.build();
185:
186: //
187: // Check that fires
188:• if (quartzTrigger.getFireTimeAfter(new Date()) == null) {
189: throw new TriggerNeverFiresException(quartzTrigger);
190: }
191:
192: //
193: // Schedule trigger
194: try {
195: getScheduler().scheduleJob(quartzTrigger);
196: } catch (SchedulerException se) {
197: throw new CannotScheduleJobException(se, kapuaJobLauncherJobDetail, triggerKey, triggerDataMap);
198: }
199: }
200:
201: private static JobDetail getJobDetail() throws CannotAddQuartzJobException, SchedulerNotAvailableException {
202:
203: JobKey jobkey = JobKey.jobKey(KapuaJobLauncher.class.getName(), "USER");
204: JobDetail kapuaJobLauncherJobDetail;
205: try {
206: kapuaJobLauncherJobDetail = getScheduler().getJobDetail(jobkey);
207:
208:• if (kapuaJobLauncherJobDetail == null) {
209: kapuaJobLauncherJobDetail = JobBuilder.newJob(KapuaJobLauncher.class)
210: .withIdentity(jobkey)
211: .storeDurably()
212: .build();
213:
214: getScheduler().addJob(kapuaJobLauncherJobDetail, false);
215: }
216: } catch (SchedulerException se) {
217: throw new CannotAddQuartzJobException(se, KapuaJobLauncher.class, jobkey);
218: }
219: return kapuaJobLauncherJobDetail;
220: }
221:
222: private static Scheduler getScheduler() throws SchedulerNotAvailableException {
223:• if (scheduler == null) {
224: initQuarztScheduler();
225: }
226:
227: return scheduler;
228: }
229:
230: private static synchronized void initQuarztScheduler() throws SchedulerNotAvailableException {
231:• if (scheduler != null) {
232: return;
233: }
234:
235: LOG.info("Initializing Quartz Scheduler instance...");
236: int attempt = 0;
237: int maxAttempt = 3;
238: do {
239: try {
240: SchedulerFactory sf = new StdSchedulerFactory();
241: scheduler = sf.getScheduler();
242: } catch (SchedulerException se) {
243:• if (attempt++ < maxAttempt) {
244: LOG.warn("Initializing Quartz Scheduler instance... ERROR! Retrying in a while ({}/{})... Error occurred: {}", attempt, maxAttempt, se.getMessage());
245: try {
246: Thread.sleep(1000);
247: } catch (InterruptedException e) {
248: Thread.currentThread().interrupt();
249: }
250: } else {
251: LOG.error("Initializing Quartz Scheduler instance... ERROR!", se);
252: throw new SchedulerNotAvailableException(se);
253: }
254: }
255:• } while (scheduler == null);
256:
257: LOG.info("Initializing Quartz Scheduler instance... DONE!");
258: }
259: }