Context module for the Micronaut Framework that extends the micronaut-inject module with additional bean container services such as job scheduling with @Scheduled, event listeners with @EventListener, and immutable configuration properties
—
Comprehensive task scheduling capabilities supporting both declarative annotation-driven scheduling and programmatic task management. Includes CRON expression support, fixed-rate/fixed-delay scheduling, and custom executor configuration.
Declarative scheduling annotation for automatic task execution with various timing strategies.
/**
* Annotation for scheduling recurring tasks
* Can be repeated on a single method for multiple schedules
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Schedules.class)
public @interface Scheduled {
/**
* CRON expression for complex scheduling patterns
* @return CRON expression string (e.g., "0 0 2 * * ?" for daily at 2 AM)
*/
String cron() default "";
/**
* Time zone ID for CRON expression evaluation
* @return Zone ID string (e.g., "America/New_York")
*/
String zoneId() default "";
/**
* Fixed delay between completion of one execution and start of next
* @return Duration string (e.g., "30s", "5m", "1h")
*/
String fixedDelay() default "";
/**
* Initial delay before first execution
* @return Duration string (e.g., "10s", "1m")
*/
String initialDelay() default "";
/**
* Fixed rate between execution starts (regardless of completion time)
* @return Duration string (e.g., "1m", "15m")
*/
String fixedRate() default "";
/**
* Named scheduler bean to use for execution
* @return Scheduler name (default: TaskExecutors.SCHEDULED)
*/
String scheduler() default TaskExecutors.SCHEDULED;
/**
* Conditional expression for execution control
* @return SpEL expression that must evaluate to true for execution
*/
String condition() default "";
}
/**
* Container annotation for multiple @Scheduled annotations
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedules {
Scheduled[] value();
}Usage Examples:
import io.micronaut.scheduling.annotation.Scheduled;
import jakarta.inject.Singleton;
@Singleton
public class ScheduledTasks {
// Fixed delay scheduling
@Scheduled(fixedDelay = "30s", initialDelay = "10s")
public void maintenanceTask() {
System.out.println("Running maintenance every 30 seconds after completion");
}
// Fixed rate scheduling
@Scheduled(fixedRate = "1m")
public void healthCheck() {
System.out.println("Health check every minute");
}
// CRON-based scheduling
@Scheduled(cron = "0 0 2 * * ?") // Daily at 2 AM
public void dailyBackup() {
System.out.println("Running daily backup");
}
// CRON with timezone
@Scheduled(cron = "0 30 9 * * MON-FRI", zoneId = "America/New_York")
public void businessHoursTask() {
System.out.println("Business hours task in NY timezone");
}
// Multiple schedules on same method
@Scheduled(cron = "0 0 6 * * ?") // 6 AM daily
@Scheduled(cron = "0 0 18 * * ?") // 6 PM daily
public void twiceDaily() {
System.out.println("Running twice daily");
}
// Conditional execution
@Scheduled(fixedRate = "5m", condition = "${app.monitoring.enabled:true}")
public void conditionalMonitoring() {
System.out.println("Conditional monitoring task");
}
// Custom executor
@Scheduled(fixedDelay = "1s", scheduler = TaskExecutors.IO)
public void ioTask() {
System.out.println("I/O task on dedicated executor");
}
}Control asynchronous execution and executor selection for scheduled and regular methods.
/**
* Execute method asynchronously on specified thread pool
* Returns CompletableFuture for async result handling
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Async {
/**
* Executor service name for async execution
* @return Executor name (default: TaskExecutors.SCHEDULED)
*/
String value() default TaskExecutors.SCHEDULED;
}
/**
* Specify which executor service to run operation on
* More explicit than @Async for executor selection
*/
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExecuteOn {
/**
* Name of configured executor service
* @return Executor service name
*/
String value();
}Usage Examples:
import io.micronaut.scheduling.annotation.Async;
import io.micronaut.scheduling.annotation.ExecuteOn;
import java.util.concurrent.CompletableFuture;
@Singleton
public class AsyncService {
@Async
public CompletableFuture<String> processDataAsync(String data) {
// Long-running operation
return CompletableFuture.completedFuture("Processed: " + data);
}
@ExecuteOn(TaskExecutors.IO)
public void fileOperation() {
// I/O intensive operation on I/O thread pool
}
@ExecuteOn(TaskExecutors.BLOCKING)
public String blockingOperation() {
// Blocking operation on dedicated blocking thread pool
return "Result";
}
@Scheduled(fixedRate = "30s")
@ExecuteOn(TaskExecutors.IO)
public void scheduledIoTask() {
// Scheduled task that runs on I/O executor
}
}Programmatic task scheduling interface for dynamic scheduling needs.
/**
* Interface for programmatic task scheduling
* Provides methods for various scheduling patterns
*/
public interface TaskScheduler {
/**
* Schedule task using CRON expression
* @param cron CRON expression string
* @param command Runnable task to execute
* @return ScheduledFuture for task control
*/
ScheduledFuture<?> schedule(String cron, Runnable command);
/**
* Schedule callable task using CRON expression
* @param cron CRON expression string
* @param command Callable task to execute
* @return ScheduledFuture with result type
*/
<V> ScheduledFuture<V> schedule(String cron, Callable<V> command);
/**
* Schedule task using CRON expression with specific timezone
* @param cron CRON expression string
* @param timezoneId Timezone ID for CRON evaluation (null for system timezone)
* @param command Runnable task to execute
* @return ScheduledFuture for task control
*/
ScheduledFuture<?> schedule(@NonNull String cron, @Nullable String timezoneId, @NonNull Runnable command);
/**
* Schedule callable task using CRON expression with specific timezone
* @param cron CRON expression string
* @param timezoneId Timezone ID for CRON evaluation (null for system timezone)
* @param command Callable task to execute
* @return ScheduledFuture with result type
*/
<V> ScheduledFuture<V> schedule(@NonNull String cron, @Nullable String timezoneId, @NonNull Callable<V> command);
/**
* Schedule task with initial delay
* @param delay Duration to wait before execution
* @param command Runnable task to execute
* @return ScheduledFuture for task control
*/
ScheduledFuture<?> schedule(Duration delay, Runnable command);
/**
* Schedule callable task with initial delay
* @param delay Duration to wait before execution
* @param callable Callable task to execute
* @return ScheduledFuture with result type
*/
<V> ScheduledFuture<V> schedule(Duration delay, Callable<V> callable);
/**
* Schedule task at fixed rate (time between execution starts)
* @param initialDelay Initial delay before first execution
* @param period Time between execution starts
* @param command Runnable task to execute
* @return ScheduledFuture for task control
*/
ScheduledFuture<?> scheduleAtFixedRate(@Nullable Duration initialDelay, Duration period, Runnable command);
/**
* Schedule task with fixed delay (time between execution end and next start)
* @param initialDelay Initial delay before first execution (nullable)
* @param delay Time between execution end and next start
* @param command Runnable task to execute
* @return ScheduledFuture for task control
*/
ScheduledFuture<?> scheduleWithFixedDelay(@Nullable Duration initialDelay, Duration delay, Runnable command);
}Usage Examples:
import io.micronaut.scheduling.TaskScheduler;
import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
@Singleton
public class DynamicScheduler {
private final TaskScheduler taskScheduler;
public DynamicScheduler(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
public ScheduledFuture<?> scheduleMaintenanceWindow(String cronExpression) {
return taskScheduler.schedule(cronExpression, () -> {
System.out.println("Maintenance window started");
performMaintenance();
});
}
public ScheduledFuture<String> scheduleReport(Duration delay) {
return taskScheduler.schedule(delay, () -> {
return generateReport();
});
}
public ScheduledFuture<?> startPeriodicBackup() {
return taskScheduler.scheduleAtFixedRate(
Duration.ofMinutes(5), // Initial delay
Duration.ofHours(1), // Every hour
this::performBackup
);
}
}Constants interface defining standard executor names for task execution.
/**
* Standard executor service names used throughout Micronaut
* Use these constants to reference configured executors
*/
public interface TaskExecutors {
/** I/O task executor for non-blocking I/O operations */
String IO = "io";
/** Blocking task executor for operations that may block threads */
String BLOCKING = "blocking";
/** Virtual threads executor (requires Java 19+ with preview or Java 21+) */
String VIRTUAL = "virtual";
/** Scheduled task executor for @Scheduled methods */
String SCHEDULED = "scheduled";
/** Message consumer executor for message processing */
String MESSAGE_CONSUMER = "consumer";
}Utility class for parsing and evaluating CRON expressions.
/**
* CRON expression parser and evaluator
* Supports standard CRON format with seconds field
*/
public class CronExpression {
/**
* Create CronExpression from string
* @param cronExpression CRON expression string (6 or 7 fields)
* @return CronExpression instance
* @throws IllegalArgumentException if expression is invalid
*/
public static CronExpression create(String cronExpression);
/**
* Calculate next execution time after the given time
* @param afterTime Reference time to find next execution after
* @return Next execution time within next 4 years
*/
public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime);
/**
* Calculate next execution time after given time with duration limit
* @param afterTime Reference time to find next execution after
* @param durationInMillis Maximum duration in milliseconds to search
* @return Next execution time within given duration
*/
public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime, long durationInMillis);
/**
* Calculate next execution time after given time with barrier limit
* @param afterTime Reference time to find next execution after
* @param dateTimeBarrier Upper limit for search
* @return Next execution time within given barrier
*/
public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime, ZonedDateTime dateTimeBarrier);
/**
* Get the underlying cron expression string
* @return The cron expression as string
*/
public String getExpression();
}Usage Examples:
import io.micronaut.scheduling.cron.CronExpression;
import java.time.ZonedDateTime;
public class CronExpressionExample {
public void demonstrateCronExpression() {
// Create CRON expression for every weekday at 9:30 AM
CronExpression cron = CronExpression.create("0 30 9 * * MON-FRI");
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime nextRun = cron.nextTimeAfter(now);
System.out.println("Next execution: " + nextRun);
System.out.println("Cron expression: " + cron.getExpression());
}
}Interface for handling exceptions that occur during scheduled task execution.
/**
* Handler for exceptions that occur during scheduled task execution
* Implement this interface to customize error handling behavior
*/
public interface TaskExceptionHandler {
/**
* Handle exception from scheduled task
* @param task The scheduled task that threw the exception
* @param throwable The exception that was thrown
*/
void handle(ScheduledFuture<?> task, Throwable throwable);
}Usage Example:
import io.micronaut.scheduling.TaskExceptionHandler;
import jakarta.inject.Singleton;
@Singleton
public class CustomTaskExceptionHandler implements TaskExceptionHandler {
@Override
public void handle(ScheduledFuture<?> task, Throwable throwable) {
logger.error("Scheduled task failed", throwable);
// Custom logic: retry, alert, etc.
if (throwable instanceof SQLException) {
// Handle database errors specially
notifyDatabaseAdmin(throwable);
}
}
}Exception thrown for scheduler configuration problems.
/**
* Exception for scheduler configuration problems
* Extends configuration exception hierarchy
*/
public class SchedulerConfigurationException extends ConfigurationException {
public SchedulerConfigurationException(String message);
public SchedulerConfigurationException(String message, Throwable cause);
}Exception thrown during task execution failures.
/**
* Runtime exception for task execution failures
* Wraps underlying exceptions from scheduled tasks
*/
public class TaskExecutionException extends RuntimeException {
public TaskExecutionException(String message);
public TaskExecutionException(String message, Throwable cause);
}Install with Tessl CLI
npx tessl i tessl/maven-io-micronaut--micronaut-context