or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-configuration.mdapplication-context.mdcaching.mdconfiguration-properties.mddependency-injection.mdevent-handling.mdformatting.mdindex.mdlifecycle-management.mdscheduling.mdvalidation.md

scheduling.mddocs/

0

# Scheduling

1

2

Task scheduling and asynchronous execution capabilities providing comprehensive support for background processing, periodic tasks, and asynchronous method execution. This includes @Scheduled and @Async annotations, TaskScheduler interfaces, and execution configuration options.

3

4

## Capabilities

5

6

### Scheduled Task Annotations

7

8

Declarative task scheduling through annotations that automatically register methods for periodic execution.

9

10

```java { .api }

11

/**

12

* An annotation that marks a method to be scheduled. Exactly one of the cron(), fixedDelay(), or fixedRate()

13

* attributes must be specified.

14

*/

15

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})

16

@Retention(RetentionPolicy.RUNTIME)

17

@Repeatable(Schedules.class)

18

public @interface Scheduled {

19

/**

20

* A cron-like expression, extending the usual UN*X definition to include triggers on the second as well as minute, hour, day of month, month and day of week.

21

* @return an expression that can be parsed to a cron schedule

22

*/

23

String cron() default "";

24

25

/**

26

* A time zone for which the cron expression will be resolved.

27

* @return a zone id (ZoneId.of(String)), or an empty String to indicate the server's local time zone

28

*/

29

String zone() default "";

30

31

/**

32

* Execute the annotated method with a fixed period between the end of the last invocation and the start of the next.

33

* @return the delay in milliseconds

34

*/

35

long fixedDelay() default -1;

36

37

/**

38

* Execute the annotated method with a fixed period between the end of the last invocation and the start of the next.

39

* @return the delay as a String value, e.g. a placeholder or a java.time.Duration compliant value

40

*/

41

String fixedDelayString() default "";

42

43

/**

44

* Execute the annotated method with a fixed period between invocations.

45

* @return the period in milliseconds

46

*/

47

long fixedRate() default -1;

48

49

/**

50

* Execute the annotated method with a fixed period between invocations.

51

* @return the period as a String value, e.g. a placeholder or a java.time.Duration compliant value

52

*/

53

String fixedRateString() default "";

54

55

/**

56

* Number of milliseconds to delay before the first execution of a fixedRate() or fixedDelay() task.

57

* @return the initial delay in milliseconds

58

*/

59

long initialDelay() default -1;

60

61

/**

62

* Number of milliseconds to delay before the first execution of a fixedRate() or fixedDelay() task.

63

* @return the initial delay as a String value, e.g. a placeholder or a java.time.Duration compliant value

64

*/

65

String initialDelayString() default "";

66

67

/**

68

* The TimeUnit to use for fixedDelay(), fixedRate(), and initialDelay() values.

69

* @return the TimeUnit to use

70

*/

71

TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

72

73

/**

74

* A qualifier value for the specified scheduler.

75

* @return the qualifier value for the scheduler

76

*/

77

String scheduler() default "";

78

}

79

80

/**

81

* Container annotation that aggregates several @Scheduled annotations.

82

*/

83

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})

84

@Retention(RetentionPolicy.RUNTIME)

85

public @interface Schedules {

86

Scheduled[] value();

87

}

88

89

/**

90

* Enables Spring's scheduled task execution capability, similar to functionality found in Spring's task namespace.

91

*/

92

@Target(ElementType.TYPE)

93

@Retention(RetentionPolicy.RUNTIME)

94

@Import(SchedulingConfiguration.class)

95

public @interface EnableScheduling {

96

}

97

```

98

99

### Asynchronous Execution Annotations

100

101

Annotations for declarative asynchronous method execution.

102

103

```java { .api }

104

/**

105

* Annotation that marks a method as a candidate for asynchronous execution.

106

* Can also be used at the type level, in which case all of the type's methods are considered as asynchronous.

107

*/

108

@Target({ElementType.TYPE, ElementType.METHOD})

109

@Retention(RetentionPolicy.RUNTIME)

110

public @interface Async {

111

/**

112

* A qualifier value for the specified async operation(s).

113

* @return the qualifier value for the async executor

114

*/

115

String value() default "";

116

}

117

118

/**

119

* Enables Spring's asynchronous method execution capability, similar to functionality found in Spring's task namespace.

120

*/

121

@Target(ElementType.TYPE)

122

@Retention(RetentionPolicy.RUNTIME)

123

@Import(AsyncConfigurationSelector.class)

124

public @interface EnableAsync {

125

/**

126

* Indicate the 'async' annotation type to be detected at either class or method level.

127

* @return the desired annotation type for async processing

128

*/

129

Class<? extends Annotation> annotation() default Async.class;

130

131

/**

132

* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to standard Java interface-based proxies.

133

* @return whether to proxy the target class

134

*/

135

boolean proxyTargetClass() default false;

136

137

/**

138

* Indicate how async advice should be applied.

139

* @return the advice mode

140

*/

141

AdviceMode mode() default AdviceMode.PROXY;

142

143

/**

144

* Indicate the order in which the AsyncAnnotationBeanPostProcessor should be applied.

145

* @return the order for the async post processor

146

*/

147

int order() default Ordered.LOWEST_PRECEDENCE;

148

}

149

```

150

151

### Task Scheduler Interfaces

152

153

Core interfaces for task scheduling functionality.

154

155

```java { .api }

156

/**

157

* Task scheduler interface that abstracts the scheduling of Runnable tasks based on different kinds of triggers.

158

*/

159

public interface TaskScheduler {

160

/**

161

* Return the clock to use for scheduling purposes.

162

* @return the clock instance (never null)

163

*/

164

default Clock getClock() {

165

return Clock.systemDefaultZone();

166

}

167

168

/**

169

* Schedule the given Runnable, invoking it whenever the trigger indicates a next execution time.

170

* @param task the Runnable to execute whenever the trigger fires

171

* @param trigger an implementation of the Trigger interface, e.g. a CronTrigger object wrapping a cron expression

172

* @return a ScheduledFuture representing pending completion of the task, or null if the given Trigger object never fires

173

*/

174

ScheduledFuture<?> schedule(Runnable task, Trigger trigger);

175

176

/**

177

* Schedule the given Runnable for execution at the given time.

178

* @param task the Runnable to execute

179

* @param startTime the desired execution time for the task

180

* @return a ScheduledFuture representing pending completion of the task

181

*/

182

ScheduledFuture<?> schedule(Runnable task, Instant startTime);

183

184

/**

185

* Schedule the given Runnable for repeated execution, starting at the given time and subsequently with the given period.

186

* @param task the Runnable to execute

187

* @param startTime the desired first execution time for the task

188

* @param period the interval between successive executions of the task

189

* @return a ScheduledFuture representing pending completion of the task

190

*/

191

ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);

192

193

/**

194

* Schedule the given Runnable for repeated execution, starting as soon as possible and subsequently with the given period.

195

* @param task the Runnable to execute

196

* @param period the interval between successive executions of the task

197

* @return a ScheduledFuture representing pending completion of the task

198

*/

199

ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Duration period);

200

201

/**

202

* Schedule the given Runnable for repeated execution, starting at the given time and subsequently with the given delay between the completion of one execution and the start of the next.

203

* @param task the Runnable to execute

204

* @param startTime the desired first execution time for the task

205

* @param delay the delay between the completion of one execution and the start of the next

206

* @return a ScheduledFuture representing pending completion of the task

207

*/

208

ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);

209

210

/**

211

* Schedule the given Runnable for repeated execution, starting as soon as possible and subsequently with the given delay between the completion of one execution and the start of the next.

212

* @param task the Runnable to execute

213

* @param delay the delay between the completion of one execution and the start of the next

214

* @return a ScheduledFuture representing pending completion of the task

215

*/

216

ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Duration delay);

217

}

218

219

/**

220

* A TaskExecutor extension exposing scheduling characteristics that are relevant to potential task submitters.

221

*/

222

public interface SchedulingTaskExecutor extends TaskExecutor {

223

/**

224

* Does this TaskExecutor prefer short-lived tasks over long-lived tasks?

225

* @return true if this executor prefers short-lived tasks

226

*/

227

default boolean prefersShortLivedTasks() {

228

return true;

229

}

230

}

231

```

232

233

### Trigger Interfaces

234

235

Interfaces for defining when scheduled tasks should execute.

236

237

```java { .api }

238

/**

239

* Common interface for trigger objects that determine the next execution time of a task that they get associated with.

240

*/

241

public interface Trigger {

242

/**

243

* Determine the next execution time according to the given trigger context.

244

* @param triggerContext context object encapsulating last execution times and last completion time

245

* @return the next execution time as defined by the trigger, or null if the trigger won't fire anymore

246

*/

247

Instant nextExecution(TriggerContext triggerContext);

248

}

249

250

/**

251

* Context object encapsulating last execution times and last completion time of a given task.

252

*/

253

public interface TriggerContext {

254

/**

255

* Return the clock to use for trigger calculation purposes.

256

* @return the clock instance (never null)

257

*/

258

default Clock getClock() {

259

return Clock.systemDefaultZone();

260

}

261

262

/**

263

* Return the last scheduled execution time of the task, or null if not scheduled before.

264

* @return the last scheduled execution time, or null if none

265

*/

266

Instant lastScheduledExecution();

267

268

/**

269

* Return the last actual execution time of the task, or null if not scheduled before.

270

* @return the last actual execution time, or null if none

271

*/

272

Instant lastActualExecution();

273

274

/**

275

* Return the last completion time of the task, or null if not scheduled before.

276

* @return the last completion time, or null if none

277

*/

278

Instant lastCompletion();

279

}

280

281

/**

282

* Trigger implementation for cron expressions.

283

*/

284

public class CronTrigger implements Trigger {

285

/**

286

* Build a CronTrigger from the pattern provided in the default time zone.

287

* @param expression a space-separated list of time fields

288

*/

289

public CronTrigger(String expression) {}

290

291

/**

292

* Build a CronTrigger from the pattern provided in the given time zone.

293

* @param expression a space-separated list of time fields

294

* @param timeZone the time zone in which the trigger times will be generated

295

*/

296

public CronTrigger(String expression, ZoneId timeZone) {}

297

298

/**

299

* Return the cron pattern that this trigger was built with.

300

* @return the cron expression

301

*/

302

public String getExpression() {}

303

304

/**

305

* Determine the next execution time according to the given trigger context.

306

* @param triggerContext context object encapsulating last execution times and last completion time

307

* @return the next execution time as defined by the trigger, or null if the trigger won't fire anymore

308

*/

309

public Instant nextExecution(TriggerContext triggerContext) {}

310

}

311

312

/**

313

* Trigger implementation for periodic task execution.

314

*/

315

public class PeriodicTrigger implements Trigger {

316

/**

317

* Create a trigger with the given period in the default time unit (milliseconds).

318

* @param period the interval between executions

319

* @param timeUnit the time unit for the period

320

*/

321

public PeriodicTrigger(Duration period) {}

322

323

/**

324

* Specify the delay between the completion of one execution and the start of the next.

325

* @param fixedRate whether to use fixed rate (true) or fixed delay (false)

326

*/

327

public void setFixedRate(boolean fixedRate) {}

328

329

/**

330

* Specify the delay before the first execution of the task.

331

* @param initialDelay the initial delay

332

*/

333

public void setInitialDelay(Duration initialDelay) {}

334

335

/**

336

* Return the interval between successive executions.

337

* @return the period for this trigger

338

*/

339

public Duration getPeriod() {}

340

341

/**

342

* Return whether this trigger uses fixed rate execution.

343

* @return true if fixed rate, false if fixed delay

344

*/

345

public boolean isFixedRate() {}

346

347

/**

348

* Return the initial delay before first execution.

349

* @return the initial delay

350

*/

351

public Duration getInitialDelay() {}

352

353

/**

354

* Determine the next execution time according to the given trigger context.

355

* @param triggerContext context object encapsulating last execution times and last completion time

356

* @return the next execution time as defined by the trigger, or null if the trigger won't fire anymore

357

*/

358

public Instant nextExecution(TriggerContext triggerContext) {}

359

}

360

```

361

362

### Async Configuration Support

363

364

Interfaces and classes for configuring asynchronous execution behavior.

365

366

```java { .api }

367

/**

368

* Interface to be implemented by @Configuration classes annotated with @EnableAsync

369

* that wish to customize the Executor instance used when processing async method invocations.

370

*/

371

public interface AsyncConfigurer {

372

/**

373

* The Executor instance to be used when processing async method invocations.

374

* @return the async executor instance

375

*/

376

default Executor getAsyncExecutor() {

377

return null;

378

}

379

380

/**

381

* The AsyncUncaughtExceptionHandler instance to be used when an exception is thrown during an asynchronous method execution with void return type.

382

* @return the async exception handler instance

383

*/

384

default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

385

return null;

386

}

387

}

388

389

/**

390

* Empty implementation of AsyncConfigurer for convenient subclassing.

391

*/

392

public class AsyncConfigurerSupport implements AsyncConfigurer {

393

/**

394

* The default implementation returns null so that the framework will use a SimpleAsyncTaskExecutor in combination with a SimpleAsyncTaskScheduler.

395

* @return null

396

*/

397

@Override

398

public Executor getAsyncExecutor() {

399

return null;

400

}

401

402

/**

403

* The default implementation returns null so that the framework will log the exception at ERROR level.

404

* @return null

405

*/

406

@Override

407

public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

408

return null;

409

}

410

}

411

412

/**

413

* Interface to be implemented by @Configuration classes annotated with @EnableScheduling

414

* that wish to register Trigger tasks in a declarative manner.

415

*/

416

public interface SchedulingConfigurer {

417

/**

418

* Callback allowing a TaskScheduler and specific Task instances to be registered against the given the ScheduledTaskRegistrar.

419

* @param taskRegistrar the registrar to be configured

420

*/

421

default void configureTasks(ScheduledTaskRegistrar taskRegistrar) {}

422

}

423

```

424

425

### Async Result Support

426

427

Classes for handling return values from asynchronous methods.

428

429

```java { .api }

430

/**

431

* A pass-through Future handle that can be used for method signatures which are declared with a Future return type for asynchronous execution.

432

*/

433

public class AsyncResult<V> implements ListenableFuture<V> {

434

/** The result value */

435

private final V value;

436

437

/** The exception */

438

private final Throwable executionException;

439

440

/**

441

* Create a new AsyncResult holder.

442

* @param value the value to pass through

443

*/

444

public AsyncResult(V value) {}

445

446

/**

447

* Create a new AsyncResult holder.

448

* @param ex the exception to pass through

449

*/

450

public AsyncResult(Throwable ex) {}

451

452

/**

453

* Cancel the execution of the task.

454

* @param mayInterruptIfRunning whether the thread executing the task should be interrupted

455

* @return false

456

*/

457

public boolean cancel(boolean mayInterruptIfRunning) {}

458

459

/**

460

* Return whether the task was cancelled.

461

* @return false

462

*/

463

public boolean isCancelled() {}

464

465

/**

466

* Return whether the task has completed.

467

* @return true

468

*/

469

public boolean isDone() {}

470

471

/**

472

* Retrieve the result value.

473

* @return the result value (never null)

474

* @throws ExecutionException if the async method threw an exception

475

* @throws InterruptedException if the current thread was interrupted while waiting

476

*/

477

public V get() throws ExecutionException {}

478

479

/**

480

* Retrieve the result value.

481

* @param timeout the maximum time to wait

482

* @param unit the time unit of the timeout argument

483

* @return the result value (never null)

484

* @throws ExecutionException if the async method threw an exception

485

* @throws InterruptedException if the current thread was interrupted while waiting

486

* @throws TimeoutException if the wait timed out

487

*/

488

public V get(long timeout, TimeUnit unit) throws ExecutionException, InterruptedException, TimeoutException {}

489

490

/**

491

* Add a completion callback to this ListenableFuture.

492

* @param callback the callback to add

493

*/

494

public void addCallback(ListenableFutureCallback<? super V> callback) {}

495

496

/**

497

* Add separate success and failure callbacks to this ListenableFuture.

498

* @param successCallback the success callback

499

* @param failureCallback the failure callback

500

*/

501

public void addCallback(SuccessCallback<? super V> successCallback, FailureCallback failureCallback) {}

502

503

/**

504

* Return a CompletableFuture that completes when this ListenableFuture completes.

505

* @return the CompletableFuture adaptation

506

*/

507

public CompletableFuture<V> completable() {}

508

}

509

```

510

511

### Exception Handling

512

513

Interfaces and classes for handling exceptions in scheduled and asynchronous execution.

514

515

```java { .api }

516

/**

517

* A strategy for handling uncaught exceptions thrown from asynchronous methods.

518

*/

519

@FunctionalInterface

520

public interface AsyncUncaughtExceptionHandler {

521

/**

522

* Handle the given uncaught exception thrown from an asynchronous method.

523

* @param ex the exception thrown from the asynchronous method

524

* @param method the asynchronous method

525

* @param params the parameters used to invoke the method

526

*/

527

void handleUncaughtException(Throwable ex, Method method, Object... params);

528

}

529

530

/**

531

* A default AsyncUncaughtExceptionHandler that simply logs the exception.

532

*/

533

public class SimpleAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {

534

/**

535

* Handle the given uncaught exception thrown from an asynchronous method.

536

* @param ex the exception thrown from the asynchronous method

537

* @param method the asynchronous method

538

* @param params the parameters used to invoke the method

539

*/

540

public void handleUncaughtException(Throwable ex, Method method, Object... params) {}

541

}

542

543

/**

544

* Exception to be thrown when an asynchronous execution attempt fails.

545

*/

546

public class SchedulingException extends RuntimeException {

547

/**

548

* Constructor for SchedulingException.

549

* @param msg the detail message

550

*/

551

public SchedulingException(String msg) {}

552

553

/**

554

* Constructor for SchedulingException.

555

* @param msg the detail message

556

* @param cause the root cause (usually from using a underlying scheduling API such as Quartz)

557

*/

558

public SchedulingException(String msg, Throwable cause) {}

559

}

560

```

561

562

### Usage Examples

563

564

**Basic Scheduled Methods:**

565

566

```java

567

import org.springframework.scheduling.annotation.Scheduled;

568

import org.springframework.scheduling.annotation.EnableScheduling;

569

import org.springframework.stereotype.Component;

570

571

@Configuration

572

@EnableScheduling

573

public class SchedulingConfig {

574

}

575

576

@Component

577

public class ScheduledTasks {

578

579

// Fixed rate execution - runs every 5 seconds

580

@Scheduled(fixedRate = 5000)

581

public void reportCurrentTime() {

582

System.out.println("Current time: " + new Date());

583

}

584

585

// Fixed delay execution - waits 3 seconds after completion before next execution

586

@Scheduled(fixedDelay = 3000)

587

public void processData() {

588

System.out.println("Processing data...");

589

// Simulate processing time

590

try {

591

Thread.sleep(2000);

592

} catch (InterruptedException e) {

593

Thread.currentThread().interrupt();

594

}

595

}

596

597

// Cron expression - runs every day at 2:00 AM

598

@Scheduled(cron = "0 0 2 * * ?")

599

public void performDailyMaintenance() {

600

System.out.println("Performing daily maintenance...");

601

}

602

603

// Initial delay with fixed rate

604

@Scheduled(initialDelay = 10000, fixedRate = 30000)

605

public void delayedTask() {

606

System.out.println("Task with initial delay");

607

}

608

609

// Using string expressions with property placeholders

610

@Scheduled(fixedDelayString = "${app.task.delay:5000}")

611

public void configurableTask() {

612

System.out.println("Configurable scheduled task");

613

}

614

615

// Using time units other than milliseconds

616

@Scheduled(fixedRate = 30, timeUnit = TimeUnit.SECONDS)

617

public void thirtySecondTask() {

618

System.out.println("Task runs every 30 seconds");

619

}

620

}

621

```

622

623

**Advanced Cron Expressions:**

624

625

```java

626

@Component

627

public class CronScheduledTasks {

628

629

// Every 15 minutes

630

@Scheduled(cron = "0 */15 * * * ?")

631

public void everyFifteenMinutes() {

632

System.out.println("Running every 15 minutes");

633

}

634

635

// Monday to Friday at 9:00 AM

636

@Scheduled(cron = "0 0 9 * * MON-FRI")

637

public void weekdayMorningTask() {

638

System.out.println("Weekday morning task");

639

}

640

641

// Last day of every month at midnight

642

@Scheduled(cron = "0 0 0 L * ?")

643

public void lastDayOfMonth() {

644

System.out.println("Last day of month task");

645

}

646

647

// Every 30 seconds on weekdays during business hours

648

@Scheduled(cron = "*/30 * 9-17 * * MON-FRI")

649

public void businessHoursTask() {

650

System.out.println("Business hours task");

651

}

652

653

// With timezone specification

654

@Scheduled(cron = "0 0 12 * * ?", zone = "America/New_York")

655

public void noonInNewYork() {

656

System.out.println("Noon in New York");

657

}

658

}

659

```

660

661

**Asynchronous Methods:**

662

663

```java

664

import org.springframework.scheduling.annotation.Async;

665

import org.springframework.scheduling.annotation.EnableAsync;

666

import java.util.concurrent.CompletableFuture;

667

import java.util.concurrent.Future;

668

669

@Configuration

670

@EnableAsync

671

public class AsyncConfig {

672

673

@Bean

674

public Executor taskExecutor() {

675

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

676

executor.setCorePoolSize(2);

677

executor.setMaxPoolSize(10);

678

executor.setQueueCapacity(100);

679

executor.setThreadNamePrefix("async-");

680

executor.initialize();

681

return executor;

682

}

683

}

684

685

@Service

686

public class AsyncService {

687

688

// Simple async method with void return

689

@Async

690

public void performAsyncTask() {

691

System.out.println("Async task started: " + Thread.currentThread().getName());

692

try {

693

Thread.sleep(2000);

694

} catch (InterruptedException e) {

695

Thread.currentThread().interrupt();

696

}

697

System.out.println("Async task completed");

698

}

699

700

// Async method returning Future

701

@Async

702

public Future<String> asyncMethodWithReturn() {

703

System.out.println("Async method with return: " + Thread.currentThread().getName());

704

try {

705

Thread.sleep(3000);

706

} catch (InterruptedException e) {

707

Thread.currentThread().interrupt();

708

return new AsyncResult<>("Interrupted");

709

}

710

return new AsyncResult<>("Task completed successfully");

711

}

712

713

// Async method returning CompletableFuture

714

@Async

715

public CompletableFuture<String> asyncWithCompletableFuture() {

716

return CompletableFuture.supplyAsync(() -> {

717

try {

718

Thread.sleep(1000);

719

return "CompletableFuture result";

720

} catch (InterruptedException e) {

721

Thread.currentThread().interrupt();

722

throw new RuntimeException(e);

723

}

724

});

725

}

726

727

// Async method with specific executor

728

@Async("taskExecutor")

729

public void asyncWithSpecificExecutor() {

730

System.out.println("Using specific executor: " + Thread.currentThread().getName());

731

}

732

}

733

```

734

735

**Custom Async Configuration:**

736

737

```java

738

@Configuration

739

@EnableAsync

740

public class CustomAsyncConfig implements AsyncConfigurer {

741

742

@Override

743

public Executor getAsyncExecutor() {

744

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

745

executor.setCorePoolSize(4);

746

executor.setMaxPoolSize(20);

747

executor.setQueueCapacity(200);

748

executor.setThreadNamePrefix("custom-async-");

749

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

750

executor.initialize();

751

return executor;

752

}

753

754

@Override

755

public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

756

return new CustomAsyncExceptionHandler();

757

}

758

759

// Additional executor for specific tasks

760

@Bean("emailExecutor")

761

public Executor emailExecutor() {

762

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

763

executor.setCorePoolSize(2);

764

executor.setMaxPoolSize(5);

765

executor.setQueueCapacity(50);

766

executor.setThreadNamePrefix("email-");

767

executor.initialize();

768

return executor;

769

}

770

}

771

772

public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

773

774

@Override

775

public void handleUncaughtException(Throwable ex, Method method, Object... params) {

776

System.err.println("Uncaught async exception in method: " + method.getName());

777

System.err.println("Parameters: " + Arrays.toString(params));

778

System.err.println("Exception: " + ex.getMessage());

779

780

// Log to monitoring system, send alerts, etc.

781

logToMonitoringSystem(ex, method, params);

782

}

783

784

private void logToMonitoringSystem(Throwable ex, Method method, Object... params) {

785

// Implementation for logging to external monitoring system

786

}

787

}

788

```

789

790

**Programmatic Task Scheduling:**

791

792

```java

793

@Service

794

public class DynamicSchedulingService {

795

796

@Autowired

797

private TaskScheduler taskScheduler;

798

799

private final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

800

801

// Schedule a task dynamically

802

public void scheduleTask(String taskId, Runnable task, String cronExpression) {

803

ScheduledFuture<?> future = taskScheduler.schedule(task, new CronTrigger(cronExpression));

804

scheduledTasks.put(taskId, future);

805

}

806

807

// Schedule with fixed delay

808

public void scheduleWithFixedDelay(String taskId, Runnable task, Duration delay) {

809

ScheduledFuture<?> future = taskScheduler.scheduleWithFixedDelay(task, delay);

810

scheduledTasks.put(taskId, future);

811

}

812

813

// Cancel a scheduled task

814

public boolean cancelTask(String taskId) {

815

ScheduledFuture<?> future = scheduledTasks.remove(taskId);

816

if (future != null) {

817

return future.cancel(false);

818

}

819

return false;

820

}

821

822

// Example dynamic task creation

823

public void createUserMaintenanceTask(String userId, String schedule) {

824

Runnable maintenanceTask = () -> {

825

System.out.println("Performing maintenance for user: " + userId);

826

// Perform user-specific maintenance

827

};

828

829

scheduleTask("user-maintenance-" + userId, maintenanceTask, schedule);

830

}

831

}

832

```

833

834

**Scheduled and Async Together:**

835

836

```java

837

@Service

838

public class ScheduledAsyncService {

839

840

@Autowired

841

private EmailService emailService;

842

843

@Autowired

844

private ReportService reportService;

845

846

// Scheduled method that triggers async operations

847

@Scheduled(cron = "0 0 8 * * MON-FRI") // Every weekday at 8 AM

848

public void sendDailyReports() {

849

System.out.println("Starting daily report generation...");

850

851

// Get list of users

852

List<User> users = userService.getAllActiveUsers();

853

854

// Send reports asynchronously for each user

855

for (User user : users) {

856

sendReportAsync(user);

857

}

858

}

859

860

@Async

861

public void sendReportAsync(User user) {

862

try {

863

// Generate report (potentially time-consuming)

864

Report report = reportService.generateUserReport(user);

865

866

// Send email

867

emailService.sendReport(user.getEmail(), report);

868

869

System.out.println("Report sent to: " + user.getEmail());

870

} catch (Exception e) {

871

System.err.println("Failed to send report to: " + user.getEmail());

872

// Log error or handle appropriately

873

}

874

}

875

876

// Another scheduled task with async processing

877

@Scheduled(fixedRate = 300000) // Every 5 minutes

878

public void processBackgroundTasks() {

879

List<BackgroundTask> tasks = taskRepository.findPendingTasks();

880

881

tasks.forEach(this::processTaskAsync);

882

}

883

884

@Async

885

public CompletableFuture<Void> processTaskAsync(BackgroundTask task) {

886

return CompletableFuture.runAsync(() -> {

887

try {

888

// Process the task

889

taskProcessor.process(task);

890

task.markCompleted();

891

taskRepository.save(task);

892

} catch (Exception e) {

893

task.markFailed();

894

taskRepository.save(task);

895

}

896

});

897

}

898

}

899

```