0
# Job Management
1
2
Job creation, configuration, and lifecycle management in Quartz. This covers the Job interface that defines work to be executed, JobDetail for job metadata and configuration, JobBuilder for fluent job creation, and JobExecutionContext for runtime information.
3
4
## Capabilities
5
6
### Job Interface
7
8
The core interface that defines the work to be executed. All application jobs must implement this interface.
9
10
```java { .api }
11
/**
12
* Interface to be implemented by classes which represent a 'job' to be performed
13
* Job instances must have a public no-argument constructor
14
*/
15
interface Job {
16
/**
17
* Execute the job. Called by the scheduler when a trigger fires
18
* @param context provides runtime information about the job execution
19
* @throws JobExecutionException if job execution fails or needs special handling
20
*/
21
void execute(JobExecutionContext context) throws JobExecutionException;
22
}
23
```
24
25
**Usage Examples:**
26
27
```java
28
// Simple job implementation
29
public class ReportJob implements Job {
30
public void execute(JobExecutionContext context) throws JobExecutionException {
31
System.out.println("Generating report at: " + new Date());
32
33
// Access job data
34
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
35
String reportType = dataMap.getString("reportType");
36
37
try {
38
generateReport(reportType);
39
} catch (Exception e) {
40
// Wrap and rethrow as JobExecutionException
41
throw new JobExecutionException("Report generation failed", e);
42
}
43
}
44
45
private void generateReport(String type) {
46
// Report generation logic
47
}
48
}
49
50
// Job with error handling and retry logic
51
public class DataProcessingJob implements Job {
52
public void execute(JobExecutionContext context) throws JobExecutionException {
53
try {
54
processData();
55
} catch (TransientException e) {
56
// Retry immediately
57
JobExecutionException jee = new JobExecutionException(e);
58
jee.setRefireImmediately(true);
59
throw jee;
60
} catch (PermanentException e) {
61
// Unschedule this trigger
62
JobExecutionException jee = new JobExecutionException(e);
63
jee.setUnscheduleFiringTrigger(true);
64
throw jee;
65
}
66
}
67
68
private void processData() throws TransientException, PermanentException {
69
// Data processing logic
70
}
71
}
72
```
73
74
### JobDetail Interface
75
76
Conveys the details of a Job instance, including identity, job class, data, and behavior configuration.
77
78
```java { .api }
79
/**
80
* Conveys the detail properties of a job instance
81
*/
82
interface JobDetail extends Serializable, Cloneable {
83
/**
84
* Get the unique key that identifies this job
85
* @return the job's key (name and group)
86
*/
87
JobKey getKey();
88
89
/**
90
* Get the human-readable description of the job
91
* @return job description or null if none set
92
*/
93
String getDescription();
94
95
/**
96
* Get the job implementation class
97
* @return the class that implements the Job interface
98
*/
99
Class<? extends Job> getJobClass();
100
101
/**
102
* Get the job data map containing job state and parameters
103
* @return job data map (never null)
104
*/
105
JobDataMap getJobDataMap();
106
107
/**
108
* Check if the job is durable (persists without triggers)
109
* @return true if job should persist when no triggers reference it
110
*/
111
boolean isDurable();
112
113
/**
114
* Check if job data should be persisted after execution
115
* @return true if JobDataMap changes should be persisted
116
*/
117
boolean isPersistJobDataAfterExecution();
118
119
/**
120
* Check if concurrent execution of this job is disallowed
121
* @return true if only one instance of this job should execute at a time
122
*/
123
boolean isConcurrentExecutionDisallowed();
124
125
/**
126
* Check if the job requests recovery after scheduler failure
127
* @return true if job should be re-executed after scheduler restart
128
*/
129
boolean requestsRecovery();
130
131
/**
132
* Get a JobBuilder configured to produce a JobDetail identical to this one
133
* @return builder for creating similar job details
134
*/
135
JobBuilder getJobBuilder();
136
}
137
```
138
139
### JobBuilder Class
140
141
Fluent builder for creating JobDetail instances with type safety and clear configuration.
142
143
```java { .api }
144
/**
145
* Builder for JobDetail instances using fluent interface
146
*/
147
class JobBuilder {
148
/**
149
* Create a new JobBuilder
150
* @return new builder instance
151
*/
152
static JobBuilder newJob();
153
154
/**
155
* Create a new JobBuilder with specified job class
156
* @param jobClass the Job implementation class
157
* @return new builder instance
158
*/
159
static JobBuilder newJob(Class<? extends Job> jobClass);
160
161
/**
162
* Set the job's identity using name only (uses DEFAULT_GROUP)
163
* @param name the job name
164
* @return this builder for method chaining
165
*/
166
JobBuilder withIdentity(String name);
167
168
/**
169
* Set the job's identity using name and group
170
* @param name the job name
171
* @param group the job group
172
* @return this builder for method chaining
173
*/
174
JobBuilder withIdentity(String name, String group);
175
176
/**
177
* Set the job's identity using a JobKey
178
* @param jobKey the complete job key
179
* @return this builder for method chaining
180
*/
181
JobBuilder withIdentity(JobKey jobKey);
182
183
/**
184
* Set the job's description
185
* @param jobDescription human-readable description
186
* @return this builder for method chaining
187
*/
188
JobBuilder withDescription(String jobDescription);
189
190
/**
191
* Set the job's implementation class
192
* @param jobClazz the Job implementation class
193
* @return this builder for method chaining
194
*/
195
JobBuilder ofType(Class<? extends Job> jobClazz);
196
197
/**
198
* Request recovery for this job (default false)
199
* @return this builder for method chaining
200
*/
201
JobBuilder requestRecovery();
202
203
/**
204
* Set recovery request flag
205
* @param jobShouldRecover if true, job will be re-executed after scheduler failure
206
* @return this builder for method chaining
207
*/
208
JobBuilder requestRecovery(boolean jobShouldRecover);
209
210
/**
211
* Make the job durable (persists without triggers)
212
* @return this builder for method chaining
213
*/
214
JobBuilder storeDurably();
215
216
/**
217
* Set job durability
218
* @param jobDurability if true, job persists when no triggers reference it
219
* @return this builder for method chaining
220
*/
221
JobBuilder storeDurably(boolean jobDurability);
222
223
/**
224
* Add a single data value to the job's data map
225
* @param key the data key
226
* @param value the data value
227
* @return this builder for method chaining
228
*/
229
JobBuilder usingJobData(String key, String value);
230
231
/**
232
* Add integer data to the job's data map
233
* @param key the data key
234
* @param value the integer value
235
* @return this builder for method chaining
236
*/
237
JobBuilder usingJobData(String key, Integer value);
238
239
/**
240
* Add long data to the job's data map
241
* @param key the data key
242
* @param value the long value
243
* @return this builder for method chaining
244
*/
245
JobBuilder usingJobData(String key, Long value);
246
247
/**
248
* Add float data to the job's data map
249
* @param key the data key
250
* @param value the float value
251
* @return this builder for method chaining
252
*/
253
JobBuilder usingJobData(String key, Float value);
254
255
/**
256
* Add double data to the job's data map
257
* @param key the data key
258
* @param value the double value
259
* @return this builder for method chaining
260
*/
261
JobBuilder usingJobData(String key, Double value);
262
263
/**
264
* Add boolean data to the job's data map
265
* @param key the data key
266
* @param value the boolean value
267
* @return this builder for method chaining
268
*/
269
JobBuilder usingJobData(String key, Boolean value);
270
271
/**
272
* Set the job's entire data map
273
* @param newJobDataMap the job data map
274
* @return this builder for method chaining
275
*/
276
JobBuilder usingJobData(JobDataMap newJobDataMap);
277
278
/**
279
* Replace the job's data map (clears existing data)
280
* @param newJobDataMap the replacement job data map
281
* @return this builder for method chaining
282
*/
283
JobBuilder setJobData(JobDataMap newJobDataMap);
284
285
/**
286
* Build the JobDetail instance
287
* @return the configured JobDetail
288
*/
289
JobDetail build();
290
}
291
```
292
293
**Usage Examples:**
294
295
```java
296
// Basic job creation
297
JobDetail job = newJob(ReportJob.class)
298
.withIdentity("dailyReport", "reports")
299
.withDescription("Generate daily sales report")
300
.build();
301
302
// Job with data and special configuration
303
JobDetail processingJob = newJob(DataProcessingJob.class)
304
.withIdentity("dataProcessor", "processing")
305
.withDescription("Process incoming data files")
306
.usingJobData("inputDir", "/data/input")
307
.usingJobData("outputDir", "/data/output")
308
.usingJobData("maxFiles", 100)
309
.usingJobData("timeout", 30000L)
310
.usingJobData("retryEnabled", true)
311
.requestRecovery()
312
.storeDurably()
313
.build();
314
315
// Job using JobDataMap
316
JobDataMap dataMap = new JobDataMap();
317
dataMap.put("config", configObject);
318
dataMap.put("database", databaseConnection);
319
320
JobDetail complexJob = newJob(ComplexProcessingJob.class)
321
.withIdentity("complexProcessor")
322
.setJobData(dataMap)
323
.build();
324
325
// Static import for cleaner syntax
326
import static org.quartz.JobBuilder.*;
327
328
JobDetail cleanJob = newJob(MyJob.class)
329
.withIdentity("myJob", "myGroup")
330
.build();
331
```
332
333
### JobDataMap Class
334
335
Container for job state and parameters that can be accessed during job execution.
336
337
```java { .api }
338
/**
339
* Holds state information for Job instances
340
* Extends Map interface for convenient data access
341
*/
342
class JobDataMap extends StringKeyDirtyFlagMap {
343
/**
344
* Create an empty JobDataMap
345
*/
346
JobDataMap();
347
348
/**
349
* Create a JobDataMap with initial data
350
* @param map initial data to populate the map
351
*/
352
JobDataMap(Map<?, ?> map);
353
354
/**
355
* Get string value with type safety
356
* @param key the data key
357
* @return string value or null
358
*/
359
String getString(String key);
360
361
/**
362
* Get boolean value with type conversion
363
* @param key the data key
364
* @return boolean value or false if not found/convertible
365
*/
366
boolean getBooleanValue(String key);
367
368
/**
369
* Get Boolean object value
370
* @param key the data key
371
* @return Boolean object or null
372
*/
373
Boolean getBoolean(String key);
374
375
/**
376
* Get char value with type conversion
377
* @param key the data key
378
* @return char value or space if not found/convertible
379
*/
380
char getCharValue(String key);
381
382
/**
383
* Get Character object value
384
* @param key the data key
385
* @return Character object or null
386
*/
387
Character getCharacter(String key);
388
389
/**
390
* Get double value with type conversion
391
* @param key the data key
392
* @return double value or 0.0 if not found/convertible
393
*/
394
double getDoubleValue(String key);
395
396
/**
397
* Get Double object value
398
* @param key the data key
399
* @return Double object or null
400
*/
401
Double getDouble(String key);
402
403
/**
404
* Get float value with type conversion
405
* @param key the data key
406
* @return float value or 0.0f if not found/convertible
407
*/
408
float getFloatValue(String key);
409
410
/**
411
* Get Float object value
412
* @param key the data key
413
* @return Float object or null
414
*/
415
Float getFloat(String key);
416
417
/**
418
* Get int value with type conversion
419
* @param key the data key
420
* @return int value or 0 if not found/convertible
421
*/
422
int getIntValue(String key);
423
424
/**
425
* Get Integer object value
426
* @param key the data key
427
* @return Integer object or null
428
*/
429
Integer getInt(String key);
430
431
/**
432
* Get long value with type conversion
433
* @param key the data key
434
* @return long value or 0L if not found/convertible
435
*/
436
long getLongValue(String key);
437
438
/**
439
* Get Long object value
440
* @param key the data key
441
* @return Long object or null
442
*/
443
Long getLong(String key);
444
}
445
```
446
447
**Usage Examples:**
448
449
```java
450
// Creating and populating JobDataMap
451
JobDataMap dataMap = new JobDataMap();
452
dataMap.put("reportType", "sales");
453
dataMap.put("quarter", 1);
454
dataMap.put("includeCharts", true);
455
dataMap.put("timeout", 5000L);
456
457
// Type-safe access in job
458
public class ReportJob implements Job {
459
public void execute(JobExecutionContext context) {
460
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
461
462
String reportType = dataMap.getString("reportType");
463
int quarter = dataMap.getIntValue("quarter");
464
boolean includeCharts = dataMap.getBooleanValue("includeCharts");
465
long timeout = dataMap.getLongValue("timeout");
466
467
generateReport(reportType, quarter, includeCharts, timeout);
468
}
469
}
470
471
// Merging with trigger data
472
JobDataMap mergedData = context.getMergedJobDataMap();
473
// Contains both job and trigger data
474
```
475
476
### JobExecutionContext Interface
477
478
Provides runtime context and information to executing jobs.
479
480
```java { .api }
481
/**
482
* Context provides runtime information to Job instances during execution
483
*/
484
interface JobExecutionContext {
485
/**
486
* Get the scheduler instance that is executing this job
487
* @return the scheduler instance
488
*/
489
Scheduler getScheduler();
490
491
/**
492
* Get the trigger that fired this job
493
* @return the firing trigger
494
*/
495
Trigger getTrigger();
496
497
/**
498
* Get the calendar associated with the trigger (if any)
499
* @return the calendar or null
500
*/
501
Calendar getCalendar();
502
503
/**
504
* Check if this is a recovery execution
505
* @return true if job is being recovered after scheduler failure
506
*/
507
boolean isRecovering();
508
509
/**
510
* Get the retry count for this execution
511
* @return number of times this job has been retried
512
*/
513
int getRefireCount();
514
515
/**
516
* Get the merged job data (job + trigger data)
517
* @return merged job data map
518
*/
519
JobDataMap getMergedJobDataMap();
520
521
/**
522
* Get the job detail for this execution
523
* @return the job detail
524
*/
525
JobDetail getJobDetail();
526
527
/**
528
* Get the job instance being executed
529
* @return the job instance
530
*/
531
Job getJobInstance();
532
533
/**
534
* Get the time this job was scheduled to fire
535
* @return the scheduled fire time
536
*/
537
Date getScheduledFireTime();
538
539
/**
540
* Get the actual time this job fired
541
* @return the actual fire time
542
*/
543
Date getFireTime();
544
545
/**
546
* Get the next time the trigger will fire
547
* @return the next fire time or null if no more firings
548
*/
549
Date getNextFireTime();
550
551
/**
552
* Get the previous time the trigger fired
553
* @return the previous fire time or null if first firing
554
*/
555
Date getPreviousFireTime();
556
557
/**
558
* Get the unique fire instance ID
559
* @return unique identifier for this execution
560
*/
561
String getFireInstanceId();
562
563
/**
564
* Get the result object from job execution
565
* @return the result object or null
566
*/
567
Object getResult();
568
569
/**
570
* Set the result object for this job execution
571
* @param result the result object
572
*/
573
void setResult(Object result);
574
575
/**
576
* Get the job run time (how long the job executed)
577
* @return job runtime in milliseconds
578
*/
579
long getJobRunTime();
580
}
581
```
582
583
**Usage Examples:**
584
585
```java
586
public class ContextAwareJob implements Job {
587
public void execute(JobExecutionContext context) throws JobExecutionException {
588
// Access scheduler information
589
Scheduler scheduler = context.getScheduler();
590
String schedulerName = scheduler.getSchedulerName();
591
592
// Access trigger information
593
Trigger trigger = context.getTrigger();
594
System.out.println("Fired by trigger: " + trigger.getKey());
595
596
// Access timing information
597
Date scheduledTime = context.getScheduledFireTime();
598
Date actualTime = context.getFireTime();
599
long delay = actualTime.getTime() - scheduledTime.getTime();
600
System.out.println("Execution delay: " + delay + "ms");
601
602
// Check if this is a recovery
603
if (context.isRecovering()) {
604
System.out.println("This is a recovery execution");
605
}
606
607
// Access merged data (job + trigger data)
608
JobDataMap mergedData = context.getMergedJobDataMap();
609
String config = mergedData.getString("config");
610
611
// Set result for listeners
612
context.setResult("Job completed successfully");
613
614
// Get unique execution ID
615
String fireId = context.getFireInstanceId();
616
System.out.println("Execution ID: " + fireId);
617
}
618
}
619
```
620
621
### JobKey Class
622
623
Unique identifier for job instances combining name and group.
624
625
```java { .api }
626
/**
627
* Uniquely identifies a JobDetail within a Scheduler
628
*/
629
class JobKey extends Key<JobKey> {
630
/**
631
* Create a JobKey with name in the default group
632
* @param name the job name
633
*/
634
JobKey(String name);
635
636
/**
637
* Create a JobKey with name and group
638
* @param name the job name
639
* @param group the job group
640
*/
641
JobKey(String name, String group);
642
643
/**
644
* Static factory method for JobKey with default group
645
* @param name the job name
646
* @return new JobKey instance
647
*/
648
static JobKey jobKey(String name);
649
650
/**
651
* Static factory method for JobKey with group
652
* @param name the job name
653
* @param group the job group
654
* @return new JobKey instance
655
*/
656
static JobKey jobKey(String name, String group);
657
}
658
```
659
660
**Usage Examples:**
661
662
```java
663
// Creating job keys
664
JobKey key1 = new JobKey("myJob");
665
JobKey key2 = new JobKey("myJob", "myGroup");
666
667
// Using static factory methods (preferred)
668
JobKey key3 = jobKey("reportJob", "reports");
669
JobKey key4 = jobKey("maintenanceJob"); // Uses DEFAULT_GROUP
670
671
// Using in job operations
672
scheduler.deleteJob(jobKey("oldJob", "cleanup"));
673
scheduler.triggerJob(jobKey("reportJob", "reports"));
674
boolean exists = scheduler.checkExists(jobKey("myJob", "myGroup"));
675
```