The DynamicTaskScheduler is a Spring component that provides dynamic scheduling capabilities for cron jobs stored in a database.It allows for real-time updates to scheduled tasks without requiring application restart.
Package |
|
Annotations |
|
Dependencies |
|
-
Dynamic Scheduling: Automatically schedules and reschedules cron jobs based on database changes
-
Real-time Updates: Listens for database changes and updates schedules accordingly
-
Validation: Validates cron expressions before scheduling
-
Error Handling: Comprehensive error handling and logging
-
Status Monitoring: Provides task status information
-
Manual Refresh: Supports manual refresh of all scheduled tasks
The scheduler maintains a ConcurrentHashMap of active scheduled tasks, where:
- Key: Task name (String)
- Value: ScheduledFuture<?> representing the scheduled task
private void scheduleAllTasks()-
Retrieves all active cron jobs from the database
-
Delegates to
updateSchedules()for actual scheduling
private void updateSchedules(List<CronJob> cronJobs)-
Updates the complete schedule with provided cron jobs
-
Cancels all existing tasks before scheduling new ones
-
Logs the number of jobs being updated
private boolean isValidCronExpression(String cronExpression)Parameters:
Name |
Type |
Description |
|
|
The cron expression to validate |
Returns: boolean - true if valid, false otherwise
Validation Rules:
* Expression must not be null or empty
* Must be parseable by Spring’s CronExpression.parse()
private void cancelAllTasks()-
Cancels all currently scheduled tasks
-
Clears the internal task registry
-
Uses non-interrupting cancellation (
cancel(false))
public void manualRefresh()-
Provides manual refresh capability for all scheduled tasks
-
Useful for administrative operations or troubleshooting
@Autowired
private DynamicTaskScheduler scheduler;
// Manual refresh of all tasks
scheduler.manualRefresh();
// Check status of all tasks
Map<String, Boolean> status = scheduler.getTaskStatus();
status.forEach((taskName, isActive) ->
System.out.println(taskName + " is " + (isActive ? "active" : "inactive"))
);The component requires the following beans to be available:
-
TaskScheduler- Spring’s task scheduler implementation -
DatabaseCronService- Service for database operations related to cron jobs
The scheduler implements comprehensive error handling:
-
Invalid Cron Expressions: Logged as errors, tasks are skipped
-
Scheduling Errors: Logged with full context including task name and expression
-
Execution Errors: Logged with job name and error details
-
Cancellation Errors: Logged as warnings, process continues
The class uses SLF4J logging with the following levels:
-
INFO: Schedule updates, task executions, manual refreshes
-
DEBUG: Individual task cancellations
-
WARN: Invalid cron expressions, cancellation errors
-
ERROR: Scheduling failures, execution failures
The implementation is thread-safe:
* Uses ConcurrentHashMap for task storage
* All operations are synchronized through the underlying Spring TaskScheduler
* Change listeners are handled safely
The class can be extended by:
-
Custom Job Execution: Modify
executeJob()to use reflection for dynamic job class instantiation -
Custom Validation: Extend
isValidCronExpression()for additional validation rules -
Custom Listeners: Add additional change listeners for monitoring
-
Metrics Integration: Add metrics collection for monitoring and alerting
Dependency |
Version |
Purpose |
Spring Framework |
6.x |
Core scheduling and dependency injection |
Jakarta EE |
10.x |
Annotations and enterprise features |
Lombok |
Latest |
Code generation and logging |
SLF4J |
Latest |
Logging abstraction |
The DatabaseCronService is a Spring service component that acts as a bridge between the database-stored cron job configurations and the dynamic task scheduling system.It provides database access methods and implements a change detection mechanism to automatically notify listeners when cron job configurations are modified in the database.
Package |
|
Annotations |
|
Dependencies |
|
-
Database Integration: Provides methods to retrieve cron jobs from the database
-
Change Detection: Automatically detects changes in cron job configurations
-
Event-Driven Architecture: Notifies listeners when changes are detected
-
Transactional Support: All database operations are properly transactional
-
Thread Safety: Uses concurrent data structures for safe multi-threaded access
-
Automatic Polling: Periodically checks for database changes every 10 seconds
The service maintains an internal cache of known cron jobs using a ConcurrentHashMap to enable efficient change detection:
-
Key: Job name (String)
-
Value:
CronJobentity representing the last known state
Database → Repository → Service → Change Detection → Listener Notification
↑ ↓
└─── Periodic Polling (10s) ←─────────┘@Transactional(readOnly = true)
public List<CronJob> getActiveCronJobs()Purpose: Retrieves all active cron jobs from the database
Returns: List<CronJob> - List of active cron jobs
Transaction: Read-only transaction
Usage:
List<CronJob> activeJobs = databaseCronService.getActiveCronJobs();@Transactional(readOnly = true)
public List<CronJob> getAllCronJobs()Purpose: Retrieves all cron jobs from the database (both active and inactive)
Returns: List<CronJob> - List of all cron jobs
Transaction: Read-only transaction
Usage:
List<CronJob> allJobs = databaseCronService.getAllCronJobs();@Setter
private Consumer<List<CronJob>> cronJobsChangeListenerPurpose: Sets a listener that will be notified when cron job changes are detected
Parameters:
Name |
Type |
Description |
|
|
Callback function to handle cron job changes |
Usage:
databaseCronService.setCronJobsChangeListener(jobs -> {
// Handle the updated list of cron jobs
updateSchedules(jobs);
});@Scheduled(fixedDelay = 10000)
@Transactional(readOnly = true)
public void checkForDatabaseChanges()Purpose: Automatically checks for changes in the database every 10 seconds
Scheduling: Fixed delay of 10,000 milliseconds (10 seconds) between executions
Process Flow:
1. Retrieves current active cron jobs from database
2. Compares with last known state using hasJobsChanged()
3. If changes detected:
- Logs the detection
- Updates internal cache with updateLastKnownJobs()
- Notifies the registered listener (if present)
4. Handles any exceptions during the process
Error Handling: All exceptions are caught and logged to prevent scheduled execution from stopping
private boolean hasJobsChanged(List<CronJob> currentJobs)Purpose: Determines if the current list of jobs differs from the last known state
Detection Criteria: - Different number of jobs - New job added (not in last known jobs) - Existing job modified (name, cron expression, or active status changed)
Returns: boolean - true if changes detected, false otherwise
The service uses Spring’s @Scheduled annotation with the following configuration:
Property |
Value |
Description |
|
10000 |
10 seconds delay between method executions |
Transaction |
Read-only |
Optimized for read operations |
@Autowired
private DatabaseCronService cronService;
// Get all active jobs
List<CronJob> activeJobs = cronService.getActiveCronJobs();
// Get all jobs (active and inactive)
List<CronJob> allJobs = cronService.getAllCronJobs();The service implements comprehensive error handling:
-
Database Exceptions: Caught during change detection polling
-
Null Safety: Checks for null listener before invocation
-
Transaction Rollback: Read-only transactions ensure no data modification on errors
The class uses SLF4J logging with the following events:
-
INFO: When changes are detected in cron jobs
-
ERROR: When exceptions occur during database change checking
The implementation ensures thread safety through:
-
ConcurrentHashMap: Thread-safe storage for last known jobs
-
Transactional Methods: Database operations are properly isolated
-
Immutable Lists: Returns immutable collections from repository calls
-
Fixed Delay Scheduling: Ensures previous execution completes before starting next
-
Read-Only Transactions: Optimized database access for query operations
-
Efficient Change Detection: Only processes changes when actually detected
-
Concurrent Cache: Minimizes lock contention in multi-threaded environments
The service integrates with:
-
Spring Data JPA: Through
CronJobRepository -
Spring Transaction Management: Via
@Transactional -
Spring Task Scheduling: Via
@Scheduled -
Event Listeners: Through the change listener mechanism
The service can be extended by:
-
Custom Change Detection: Override
jobEquals()for additional comparison criteria -
Multiple Listeners: Extend to support multiple change listeners
-
Configurable Polling: Make the fixed delay configurable via properties
-
Metrics Integration: Add performance and change detection metrics
-
Custom Filtering: Add methods for filtered job retrieval