or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

calendar-management.mdcore-scheduling.mdenterprise-features.mdexception-handling.mdindex.mdjob-management.mdlisteners-events.mdmatcher-framework.mdpersistence-storage.mdschedule-builders.mdtrigger-management.mdutilities-helpers.md

exception-handling.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for handling scheduling errors, job execution problems, and configuration issues in Quartz. The exception system provides detailed error information and allows for sophisticated error handling strategies.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

### SchedulerException

9

10

Base exception for all Quartz scheduler-related errors, providing the foundation for the exception hierarchy.

11

12

```java { .api }

13

/**

14

* Base exception for all Quartz scheduler errors

15

*/

16

class SchedulerException extends Exception {

17

/**

18

* Create exception with no message

19

*/

20

SchedulerException();

21

22

/**

23

* Create exception with message

24

* @param msg the error message

25

*/

26

SchedulerException(String msg);

27

28

/**

29

* Create exception wrapping another throwable

30

* @param cause the underlying cause

31

*/

32

SchedulerException(Throwable cause);

33

34

/**

35

* Create exception with message and underlying cause

36

* @param msg the error message

37

* @param cause the underlying cause

38

*/

39

SchedulerException(String msg, Throwable cause);

40

41

/**

42

* Get the underlying exception that caused this scheduler exception

43

* @return the wrapped exception or null

44

*/

45

Throwable getUnderlyingException();

46

47

/**

48

* Get string representation including underlying exception

49

* @return formatted string with full error details

50

*/

51

String toString();

52

}

53

```

54

55

### Job Execution Exceptions

56

57

### JobExecutionException

58

59

Exception thrown by job implementations to indicate execution problems and control trigger behavior.

60

61

```java { .api }

62

/**

63

* Exception thrown by Job implementations to indicate execution problems

64

* Provides control over trigger behavior after job failure

65

*/

66

class JobExecutionException extends SchedulerException {

67

/**

68

* Create exception with no special instructions

69

*/

70

JobExecutionException();

71

72

/**

73

* Create exception wrapping another throwable

74

* @param cause the underlying cause of job failure

75

*/

76

JobExecutionException(Throwable cause);

77

78

/**

79

* Create exception with message

80

* @param msg description of the job failure

81

*/

82

JobExecutionException(String msg);

83

84

/**

85

* Create exception with refire instruction

86

* @param refireImmediately if true, job will be re-executed immediately

87

*/

88

JobExecutionException(boolean refireImmediately);

89

90

/**

91

* Create exception with cause and refire instruction

92

* @param cause the underlying cause

93

* @param refireImmediately if true, job will be re-executed immediately

94

*/

95

JobExecutionException(Throwable cause, boolean refireImmediately);

96

97

/**

98

* Set whether the job should be re-executed immediately

99

* @param refire true to re-execute job immediately

100

*/

101

void setRefireImmediately(boolean refire);

102

103

/**

104

* Check if job should be re-executed immediately

105

* @return true if job should be refired immediately

106

*/

107

boolean refireImmediately();

108

109

/**

110

* Set whether the firing trigger should be unscheduled

111

* @param unscheduleTriggger true to unschedule the trigger that fired

112

*/

113

void setUnscheduleFiringTrigger(boolean unscheduleTriggger);

114

115

/**

116

* Check if the firing trigger should be unscheduled

117

* @return true if firing trigger should be unscheduled

118

*/

119

boolean unscheduleFiringTrigger();

120

121

/**

122

* Set whether all triggers for this job should be unscheduled

123

* @param unscheduleAllTriggers true to unschedule all job triggers

124

*/

125

void setUnscheduleAllTriggers(boolean unscheduleAllTriggers);

126

127

/**

128

* Check if all triggers for this job should be unscheduled

129

* @return true if all job triggers should be unscheduled

130

*/

131

boolean unscheduleAllTriggers();

132

}

133

```

134

135

**Usage Examples:**

136

137

```java

138

public class ResilientJob implements Job {

139

private static final int MAX_RETRIES = 3;

140

141

public void execute(JobExecutionContext context) throws JobExecutionException {

142

try {

143

performWork();

144

} catch (TransientException e) {

145

// Retry immediately for transient errors

146

int retryCount = context.getRefireCount();

147

if (retryCount < MAX_RETRIES) {

148

JobExecutionException jee = new JobExecutionException(

149

"Transient error, retrying (attempt " + (retryCount + 1) + ")", e);

150

jee.setRefireImmediately(true);

151

throw jee;

152

} else {

153

// Too many retries, unschedule this trigger

154

JobExecutionException jee = new JobExecutionException(

155

"Max retries exceeded, unscheduling trigger", e);

156

jee.setUnscheduleFiringTrigger(true);

157

throw jee;

158

}

159

} catch (PermanentException e) {

160

// Permanent error, unschedule all triggers for this job

161

JobExecutionException jee = new JobExecutionException(

162

"Permanent error, unscheduling all triggers", e);

163

jee.setUnscheduleAllTriggers(true);

164

throw jee;

165

} catch (Exception e) {

166

// Generic error, just fail this execution

167

throw new JobExecutionException("Job execution failed", e);

168

}

169

}

170

171

private void performWork() throws TransientException, PermanentException {

172

// Job implementation

173

}

174

}

175

```

176

177

### Persistence Exceptions

178

179

### JobPersistenceException

180

181

Exception indicating problems with job store persistence operations.

182

183

```java { .api }

184

/**

185

* Exception indicating job store persistence problems

186

*/

187

class JobPersistenceException extends SchedulerException {

188

/**

189

* Create persistence exception with no message

190

*/

191

JobPersistenceException();

192

193

/**

194

* Create persistence exception with message

195

* @param msg description of persistence problem

196

*/

197

JobPersistenceException(String msg);

198

199

/**

200

* Create persistence exception wrapping another throwable

201

* @param cause the underlying persistence error

202

*/

203

JobPersistenceException(Throwable cause);

204

205

/**

206

* Create persistence exception with message and cause

207

* @param msg description of persistence problem

208

* @param cause the underlying persistence error

209

*/

210

JobPersistenceException(String msg, Throwable cause);

211

}

212

```

213

214

### ObjectAlreadyExistsException

215

216

Exception thrown when attempting to store jobs, triggers, or calendars that already exist.

217

218

```java { .api }

219

/**

220

* Exception thrown when trying to store objects that already exist

221

*/

222

class ObjectAlreadyExistsException extends JobPersistenceException {

223

/**

224

* Create exception for generic object conflict

225

*/

226

ObjectAlreadyExistsException();

227

228

/**

229

* Create exception with custom message

230

* @param msg description of the conflict

231

*/

232

ObjectAlreadyExistsException(String msg);

233

234

/**

235

* Create exception for JobDetail conflict with auto-generated message

236

* @param jobDetail the conflicting job detail

237

*/

238

ObjectAlreadyExistsException(JobDetail jobDetail);

239

240

/**

241

* Create exception for Trigger conflict with auto-generated message

242

* @param trigger the conflicting trigger

243

*/

244

ObjectAlreadyExistsException(Trigger trigger);

245

}

246

```

247

248

**Usage Examples:**

249

250

```java

251

try {

252

// Try to add a job that might already exist

253

scheduler.addJob(jobDetail, false); // replace = false

254

} catch (ObjectAlreadyExistsException e) {

255

System.out.println("Job already exists: " + e.getMessage());

256

// Handle conflict - maybe update existing job instead

257

scheduler.addJob(jobDetail, true); // replace = true

258

} catch (JobPersistenceException e) {

259

System.err.println("Database error: " + e.getMessage());

260

// Handle persistence problems

261

} catch (SchedulerException e) {

262

System.err.println("Scheduler error: " + e.getMessage());

263

// Handle general scheduler problems

264

}

265

```

266

267

### Configuration Exceptions

268

269

### SchedulerConfigException

270

271

Exception indicating problems with scheduler configuration.

272

273

```java { .api }

274

/**

275

* Exception indicating scheduler configuration problems

276

*/

277

class SchedulerConfigException extends SchedulerException {

278

/**

279

* Create configuration exception with no message

280

*/

281

SchedulerConfigException();

282

283

/**

284

* Create configuration exception with message

285

* @param msg description of configuration problem

286

*/

287

SchedulerConfigException(String msg);

288

289

/**

290

* Create configuration exception wrapping another throwable

291

* @param cause the underlying configuration error

292

*/

293

SchedulerConfigException(Throwable cause);

294

295

/**

296

* Create configuration exception with message and cause

297

* @param msg description of configuration problem

298

* @param cause the underlying configuration error

299

*/

300

SchedulerConfigException(String msg, Throwable cause);

301

}

302

```

303

304

**Usage Examples:**

305

306

```java

307

try {

308

// Configure scheduler with properties

309

Properties props = new Properties();

310

props.setProperty("org.quartz.threadPool.class", "InvalidThreadPoolClass");

311

312

SchedulerFactory factory = new StdSchedulerFactory(props);

313

Scheduler scheduler = factory.getScheduler();

314

} catch (SchedulerConfigException e) {

315

System.err.println("Configuration error: " + e.getMessage());

316

// Handle configuration problems - maybe load default config

317

SchedulerFactory defaultFactory = new StdSchedulerFactory();

318

Scheduler scheduler = defaultFactory.getScheduler();

319

} catch (SchedulerException e) {

320

System.err.println("General scheduler error: " + e.getMessage());

321

}

322

```

323

324

### Job Interruption Exceptions

325

326

### UnableToInterruptJobException

327

328

Exception thrown when job interruption fails.

329

330

```java { .api }

331

/**

332

* Exception thrown when job interruption fails

333

*/

334

class UnableToInterruptJobException extends SchedulerException {

335

/**

336

* Create interruption exception with no message

337

*/

338

UnableToInterruptJobException();

339

340

/**

341

* Create interruption exception with message

342

* @param msg description of interruption problem

343

*/

344

UnableToInterruptJobException(String msg);

345

346

/**

347

* Create interruption exception wrapping another throwable

348

* @param cause the underlying interruption error

349

*/

350

UnableToInterruptJobException(Throwable cause);

351

352

/**

353

* Create interruption exception with message and cause

354

* @param msg description of interruption problem

355

* @param cause the underlying interruption error

356

*/

357

UnableToInterruptJobException(String msg, Throwable cause);

358

}

359

```

360

361

**Usage Examples:**

362

363

```java

364

try {

365

// Try to interrupt a running job

366

boolean interrupted = scheduler.interrupt(jobKey("longRunningJob"));

367

if (!interrupted) {

368

System.out.println("Job was not running");

369

}

370

} catch (UnableToInterruptJobException e) {

371

System.err.println("Could not interrupt job: " + e.getMessage());

372

// Handle interruption failure - maybe try shutdown instead

373

} catch (SchedulerException e) {

374

System.err.println("Scheduler error during interrupt: " + e.getMessage());

375

}

376

377

// Implementing interruptible job

378

public class InterruptibleJob implements InterruptableJob {

379

private volatile boolean interrupted = false;

380

381

public void execute(JobExecutionContext context) throws JobExecutionException {

382

for (int i = 0; i < 1000 && !interrupted; i++) {

383

// Do work in chunks, checking interrupt flag

384

processItem(i);

385

386

if (Thread.currentThread().isInterrupted()) {

387

interrupted = true;

388

throw new JobExecutionException("Job was interrupted");

389

}

390

}

391

}

392

393

public void interrupt() throws UnableToInterruptJobException {

394

this.interrupted = true;

395

// Additional cleanup if needed

396

try {

397

cleanup();

398

} catch (Exception e) {

399

throw new UnableToInterruptJobException("Cleanup failed during interrupt", e);

400

}

401

}

402

403

private void processItem(int item) {

404

// Process individual item

405

}

406

407

private void cleanup() {

408

// Cleanup resources

409

}

410

}

411

```

412

413

### Exception Handling Best Practices

414

415

### Error Handling Strategies

416

417

```java

418

// Comprehensive error handling in job implementation

419

public class RobustJob implements Job {

420

private static final Logger logger = LoggerFactory.getLogger(RobustJob.class);

421

422

public void execute(JobExecutionContext context) throws JobExecutionException {

423

String jobName = context.getJobDetail().getKey().getName();

424

425

try {

426

logger.info("Starting job: {}", jobName);

427

428

// Main job logic

429

performJobWork(context);

430

431

logger.info("Job completed successfully: {}", jobName);

432

433

} catch (RetryableException e) {

434

logger.warn("Retryable error in job {}: {}", jobName, e.getMessage());

435

handleRetryableError(context, e);

436

437

} catch (NonRetryableException e) {

438

logger.error("Non-retryable error in job {}: {}", jobName, e.getMessage(), e);

439

handleNonRetryableError(context, e);

440

441

} catch (Exception e) {

442

logger.error("Unexpected error in job {}: {}", jobName, e.getMessage(), e);

443

handleUnexpectedError(context, e);

444

}

445

}

446

447

private void handleRetryableError(JobExecutionContext context, Exception e)

448

throws JobExecutionException {

449

int maxRetries = context.getJobDetail().getJobDataMap().getIntValue("maxRetries");

450

int currentRetries = context.getRefireCount();

451

452

if (currentRetries < maxRetries) {

453

JobExecutionException jee = new JobExecutionException(e);

454

jee.setRefireImmediately(true);

455

throw jee;

456

} else {

457

JobExecutionException jee = new JobExecutionException("Max retries exceeded", e);

458

jee.setUnscheduleFiringTrigger(true);

459

throw jee;

460

}

461

}

462

463

private void handleNonRetryableError(JobExecutionContext context, Exception e)

464

throws JobExecutionException {

465

JobExecutionException jee = new JobExecutionException("Non-retryable error", e);

466

jee.setUnscheduleAllTriggers(true);

467

throw jee;

468

}

469

470

private void handleUnexpectedError(JobExecutionContext context, Exception e)

471

throws JobExecutionException {

472

// Log for investigation but don't unschedule

473

throw new JobExecutionException("Unexpected error occurred", e);

474

}

475

476

private void performJobWork(JobExecutionContext context)

477

throws RetryableException, NonRetryableException {

478

// Job implementation

479

}

480

}

481

482

// Exception handling in scheduler operations

483

public class SchedulerManager {

484

private static final Logger logger = LoggerFactory.getLogger(SchedulerManager.class);

485

486

public void scheduleJobSafely(JobDetail job, Trigger trigger) {

487

try {

488

scheduler.scheduleJob(job, trigger);

489

logger.info("Successfully scheduled job: {}", job.getKey());

490

491

} catch (ObjectAlreadyExistsException e) {

492

logger.warn("Job already exists, replacing: {}", job.getKey());

493

try {

494

scheduler.deleteJob(job.getKey());

495

scheduler.scheduleJob(job, trigger);

496

} catch (SchedulerException se) {

497

logger.error("Failed to replace existing job: {}", job.getKey(), se);

498

throw new RuntimeException("Could not schedule job", se);

499

}

500

501

} catch (SchedulerConfigException e) {

502

logger.error("Configuration error scheduling job: {}", job.getKey(), e);

503

throw new IllegalStateException("Scheduler misconfigured", e);

504

505

} catch (JobPersistenceException e) {

506

logger.error("Persistence error scheduling job: {}", job.getKey(), e);

507

// Maybe try with in-memory fallback

508

509

} catch (SchedulerException e) {

510

logger.error("General error scheduling job: {}", job.getKey(), e);

511

throw new RuntimeException("Could not schedule job", e);

512

}

513

}

514

}

515

```