or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actuator-integration.mdauto-configuration.mdconfiguration-properties.mdindex.mdscheduler-customization.md

scheduler-customization.mddocs/

0

# Scheduler Customization

1

2

Interfaces and annotations for customizing scheduler behavior, data sources, and transaction managers. Enables fine-grained control over Quartz configuration beyond what's available through standard properties.

3

4

## Capabilities

5

6

### SchedulerFactoryBeanCustomizer

7

8

Functional interface that allows programmatic customization of the SchedulerFactoryBean before it's fully initialized.

9

10

```java { .api }

11

/**

12

* Callback interface for customizing SchedulerFactoryBean

13

* Implement this interface to apply custom configuration that cannot be achieved through properties

14

*/

15

@FunctionalInterface

16

public interface SchedulerFactoryBeanCustomizer {

17

18

/**

19

* Customize the SchedulerFactoryBean before initialization

20

* @param schedulerFactoryBean The scheduler factory bean to customize

21

*/

22

void customize(SchedulerFactoryBean schedulerFactoryBean);

23

}

24

```

25

26

**Usage Examples:**

27

28

```java

29

@Configuration

30

public class QuartzCustomizerConfiguration {

31

32

@Bean

33

public SchedulerFactoryBeanCustomizer schedulerCustomizer() {

34

return schedulerFactoryBean -> {

35

// Set custom scheduler context data

36

Map<String, Object> schedulerContextMap = new HashMap<>();

37

schedulerContextMap.put("applicationName", "MyApplication");

38

schedulerContextMap.put("environment", "production");

39

schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap);

40

41

// Set custom configuration location

42

schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz-custom.properties"));

43

44

// Configure application context integration

45

schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");

46

47

// Set custom scheduler listeners

48

schedulerFactoryBean.setGlobalJobListeners(new CustomJobListener());

49

schedulerFactoryBean.setGlobalTriggerListeners(new CustomTriggerListener());

50

};

51

}

52

53

@Bean

54

public SchedulerFactoryBeanCustomizer dataSourceCustomizer(

55

@Qualifier("quartzDataSource") DataSource quartzDataSource) {

56

return schedulerFactoryBean -> {

57

schedulerFactoryBean.setDataSource(quartzDataSource);

58

schedulerFactoryBean.setNonTransactionalDataSource(quartzDataSource);

59

};

60

}

61

62

@Bean

63

public SchedulerFactoryBeanCustomizer threadPoolCustomizer() {

64

return schedulerFactoryBean -> {

65

Properties quartzProperties = new Properties();

66

quartzProperties.setProperty("org.quartz.threadPool.threadCount", "20");

67

quartzProperties.setProperty("org.quartz.threadPool.threadPriority", "5");

68

quartzProperties.setProperty("org.quartz.threadPool.class",

69

"org.quartz.simpl.SimpleThreadPool");

70

71

schedulerFactoryBean.setQuartzProperties(quartzProperties);

72

};

73

}

74

}

75

```

76

77

### QuartzDataSource Annotation

78

79

Qualifier annotation for specifying a dedicated DataSource for Quartz operations, separate from the application's primary DataSource.

80

81

```java { .api }

82

/**

83

* Qualifier annotation for DataSource to be injected into Quartz auto-configuration

84

* Used when you want to use a separate database for Quartz job storage

85

* Can be applied to secondary DataSource when another is marked as @Primary

86

*/

87

@Target({

88

ElementType.FIELD,

89

ElementType.METHOD,

90

ElementType.PARAMETER,

91

ElementType.TYPE,

92

ElementType.ANNOTATION_TYPE

93

})

94

@Retention(RetentionPolicy.RUNTIME)

95

@Documented

96

@Qualifier

97

public @interface QuartzDataSource {

98

}

99

```

100

101

**Usage Examples:**

102

103

```java

104

@Configuration

105

public class DataSourceConfiguration {

106

107

// Primary DataSource for application data

108

@Bean

109

@Primary

110

@ConfigurationProperties("spring.datasource")

111

public DataSource primaryDataSource() {

112

return DataSourceBuilder.create().build();

113

}

114

115

// Dedicated DataSource for Quartz

116

@Bean

117

@QuartzDataSource

118

@ConfigurationProperties("spring.datasource.quartz")

119

public DataSource quartzDataSource() {

120

return DataSourceBuilder.create().build();

121

}

122

123

// Using QuartzDataSource in custom components

124

@Service

125

public class QuartzManagementService {

126

127

private final JdbcTemplate quartzJdbcTemplate;

128

129

public QuartzManagementService(@QuartzDataSource DataSource quartzDataSource) {

130

this.quartzJdbcTemplate = new JdbcTemplate(quartzDataSource);

131

}

132

133

public List<String> getJobNames() {

134

return quartzJdbcTemplate.queryForList(

135

"SELECT JOB_NAME FROM QRTZ_JOB_DETAILS", String.class);

136

}

137

}

138

}

139

```

140

141

```properties

142

# Primary database configuration

143

spring.datasource.url=jdbc:postgresql://localhost:5432/myapp

144

spring.datasource.username=app_user

145

spring.datasource.password=app_password

146

147

# Quartz database configuration

148

spring.datasource.quartz.url=jdbc:postgresql://localhost:5432/quartz

149

spring.datasource.quartz.username=quartz_user

150

spring.datasource.quartz.password=quartz_password

151

```

152

153

### QuartzTransactionManager Annotation

154

155

Qualifier annotation for specifying a dedicated PlatformTransactionManager for Quartz operations.

156

157

```java { .api }

158

/**

159

* Qualifier annotation for TransactionManager to be injected into Quartz auto-configuration

160

* Used when you want to use a separate transaction manager for Quartz operations

161

* Can be applied to secondary transaction manager when another is marked as @Primary

162

*/

163

@Target({

164

ElementType.FIELD,

165

ElementType.METHOD,

166

ElementType.PARAMETER,

167

ElementType.TYPE,

168

ElementType.ANNOTATION_TYPE

169

})

170

@Retention(RetentionPolicy.RUNTIME)

171

@Documented

172

@Qualifier

173

public @interface QuartzTransactionManager {

174

}

175

```

176

177

**Usage Examples:**

178

179

```java

180

@Configuration

181

@EnableTransactionManagement

182

public class TransactionManagerConfiguration {

183

184

// Primary transaction manager for application

185

@Bean

186

@Primary

187

public PlatformTransactionManager primaryTransactionManager(

188

@Primary DataSource primaryDataSource) {

189

return new DataSourceTransactionManager(primaryDataSource);

190

}

191

192

// Dedicated transaction manager for Quartz

193

@Bean

194

@QuartzTransactionManager

195

public PlatformTransactionManager quartzTransactionManager(

196

@QuartzDataSource DataSource quartzDataSource) {

197

DataSourceTransactionManager txManager = new DataSourceTransactionManager(quartzDataSource);

198

txManager.setNestedTransactionAllowed(true);

199

return txManager;

200

}

201

202

// JTA transaction manager for distributed transactions

203

@Bean

204

@QuartzTransactionManager

205

public JtaTransactionManager quartzJtaTransactionManager() {

206

JtaTransactionManager jtaTxManager = new JtaTransactionManager();

207

jtaTxManager.setAllowCustomIsolationLevels(true);

208

return jtaTxManager;

209

}

210

}

211

212

// Using in a custom job with transaction support

213

@Component

214

public class TransactionalJob implements Job {

215

216

@Autowired

217

@QuartzTransactionManager

218

private PlatformTransactionManager quartzTransactionManager;

219

220

@Override

221

public void execute(JobExecutionContext context) throws JobExecutionException {

222

TransactionTemplate transactionTemplate =

223

new TransactionTemplate(quartzTransactionManager);

224

225

transactionTemplate.execute(status -> {

226

// Perform transactional operations

227

processData();

228

updateJobStatus();

229

return null;

230

});

231

}

232

}

233

```

234

235

## Advanced Customization Patterns

236

237

### Custom Job Factory

238

239

```java

240

@Configuration

241

public class CustomJobFactoryConfiguration {

242

243

@Bean

244

public SchedulerFactoryBeanCustomizer jobFactoryCustomizer(

245

ApplicationContext applicationContext) {

246

return schedulerFactoryBean -> {

247

CustomSpringBeanJobFactory jobFactory = new CustomSpringBeanJobFactory();

248

jobFactory.setApplicationContext(applicationContext);

249

schedulerFactoryBean.setJobFactory(jobFactory);

250

};

251

}

252

}

253

254

public class CustomSpringBeanJobFactory extends SpringBeanJobFactory {

255

256

@Override

257

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {

258

Object jobInstance = super.createJobInstance(bundle);

259

260

// Apply custom initialization logic

261

if (jobInstance instanceof CustomInitializable) {

262

((CustomInitializable) jobInstance).initialize();

263

}

264

265

return jobInstance;

266

}

267

}

268

```

269

270

### Scheduler Listeners

271

272

```java

273

@Configuration

274

public class SchedulerListenerConfiguration {

275

276

@Bean

277

public SchedulerFactoryBeanCustomizer listenerCustomizer() {

278

return schedulerFactoryBean -> {

279

schedulerFactoryBean.setSchedulerListeners(

280

new CustomSchedulerListener()

281

);

282

283

schedulerFactoryBean.setGlobalJobListeners(

284

new CustomJobListener(),

285

new AuditJobListener()

286

);

287

288

schedulerFactoryBean.setGlobalTriggerListeners(

289

new CustomTriggerListener()

290

);

291

};

292

}

293

}

294

295

public class CustomSchedulerListener implements SchedulerListener {

296

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

297

298

@Override

299

public void schedulerStarted() {

300

logger.info("Scheduler started successfully");

301

// Perform startup tasks

302

}

303

304

@Override

305

public void schedulerShutdown() {

306

logger.info("Scheduler shutting down");

307

// Perform cleanup tasks

308

}

309

310

// Other methods...

311

}

312

```

313

314

### Plugin Configuration

315

316

```java

317

@Configuration

318

public class QuartzPluginConfiguration {

319

320

@Bean

321

public SchedulerFactoryBeanCustomizer pluginCustomizer() {

322

return schedulerFactoryBean -> {

323

Properties properties = new Properties();

324

325

// Job initialization plugin

326

properties.setProperty("org.quartz.plugin.jobInitializer.class",

327

"org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin");

328

properties.setProperty("org.quartz.plugin.jobInitializer.fileNames",

329

"jobs.xml");

330

properties.setProperty("org.quartz.plugin.jobInitializer.failOnFileNotFound",

331

"true");

332

333

// Logging plugin

334

properties.setProperty("org.quartz.plugin.triggHistory.class",

335

"org.quartz.plugins.history.LoggingTriggerHistoryPlugin");

336

properties.setProperty("org.quartz.plugin.triggHistory.triggerFiredMessage",

337

"Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}");

338

339

schedulerFactoryBean.setQuartzProperties(properties);

340

};

341

}

342

}

343

```

344

345

### Conditional Customization

346

347

```java

348

@Configuration

349

public class ConditionalQuartzConfiguration {

350

351

@Bean

352

@ConditionalOnProperty(name = "app.quartz.clustering.enabled", havingValue = "true")

353

public SchedulerFactoryBeanCustomizer clusteringCustomizer() {

354

return schedulerFactoryBean -> {

355

Properties clusterProps = new Properties();

356

clusterProps.setProperty("org.quartz.jobStore.isClustered", "true");

357

clusterProps.setProperty("org.quartz.jobStore.clusterCheckinInterval", "20000");

358

clusterProps.setProperty("org.quartz.scheduler.instanceId", "AUTO");

359

360

schedulerFactoryBean.setQuartzProperties(clusterProps);

361

};

362

}

363

364

@Bean

365

@ConditionalOnMissingBean(name = "quartzDataSource")

366

public SchedulerFactoryBeanCustomizer memoryJobStoreCustomizer() {

367

return schedulerFactoryBean -> {

368

Properties memoryProps = new Properties();

369

memoryProps.setProperty("org.quartz.jobStore.class",

370

"org.quartz.simpl.RAMJobStore");

371

372

schedulerFactoryBean.setQuartzProperties(memoryProps);

373

};

374

}

375

}

376

```

377

378

## Error Handling and Best Practices

379

380

### Customizer Ordering

381

382

```java

383

@Configuration

384

public class OrderedCustomizerConfiguration {

385

386

@Bean

387

@Order(1)

388

public SchedulerFactoryBeanCustomizer dataSourceCustomizer() {

389

return schedulerFactoryBean -> {

390

// Configure DataSource first

391

};

392

}

393

394

@Bean

395

@Order(2)

396

public SchedulerFactoryBeanCustomizer propertiesCustomizer() {

397

return schedulerFactoryBean -> {

398

// Configure properties after DataSource

399

};

400

}

401

402

@Bean

403

@Order(3)

404

public SchedulerFactoryBeanCustomizer listenersCustomizer() {

405

return schedulerFactoryBean -> {

406

// Configure listeners last

407

};

408

}

409

}

410

```

411

412

### Error Handling

413

414

```java

415

@Bean

416

public SchedulerFactoryBeanCustomizer safeCustomizer() {

417

return schedulerFactoryBean -> {

418

try {

419

// Apply customizations

420

schedulerFactoryBean.setSchedulerName("CustomScheduler");

421

} catch (Exception e) {

422

logger.error("Failed to customize scheduler", e);

423

// Fallback to default configuration

424

}

425

};

426

}

427

```