CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-autoconfigure

Spring Boot AutoConfigure provides auto-configuration capabilities that automatically configure Spring applications based on jar dependencies present on the classpath

Pending
Overview
Eval results
Files

task-execution.mddocs/reference/

Task Execution and Scheduling

Spring Boot AutoConfigure provides configuration properties for task execution and scheduling, allowing fine-grained control over thread pools, concurrency limits, and shutdown behavior for asynchronous task processing and scheduled tasks.

Imports

import org.springframework.boot.autoconfigure.task.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

Task Execution Configuration

TaskExecutionProperties

Configuration properties for task execution with support for both simple and pool-based executors.

@ConfigurationProperties("spring.task.execution")
public class TaskExecutionProperties {
    /**
     * Get simple executor configuration.
     */
    public Simple getSimple();

    /**
     * Get pool executor configuration.
     */
    public Pool getPool();

    /**
     * Get shutdown configuration.
     */
    public Shutdown getShutdown();

    /**
     * Determine when the task executor is to be created.
     * Default is AUTO (create only if no user-defined executor present).
     */
    public Mode getMode();
    public void setMode(Mode mode);

    /**
     * Prefix to use for the names of newly created threads.
     * Default is "task-".
     */
    public String getThreadNamePrefix();
    public void setThreadNamePrefix(String threadNamePrefix);

    /**
     * Simple executor configuration for lightweight concurrency control.
     */
    public static class Simple {
        /**
         * Whether to cancel remaining tasks on close.
         * Only recommended if threads are commonly expected to be stuck.
         * Default is false.
         */
        public boolean isCancelRemainingTasksOnClose();
        public void setCancelRemainingTasksOnClose(boolean cancelRemainingTasksOnClose);

        /**
         * Whether to reject tasks when the concurrency limit has been reached.
         * Default is false.
         */
        public boolean isRejectTasksWhenLimitReached();
        public void setRejectTasksWhenLimitReached(boolean rejectTasksWhenLimitReached);

        /**
         * Set the maximum number of parallel accesses allowed.
         * -1 indicates no concurrency limit at all.
         * Null means no limit is set.
         */
        public Integer getConcurrencyLimit();
        public void setConcurrencyLimit(Integer concurrencyLimit);
    }

    /**
     * Pool executor configuration for ThreadPoolTaskExecutor.
     */
    public static class Pool {
        /**
         * Queue capacity for pending tasks.
         * An unbounded capacity does not increase the pool and therefore ignores max-size.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is Integer.MAX_VALUE (unbounded).
         */
        public int getQueueCapacity();
        public void setQueueCapacity(int queueCapacity);

        /**
         * Core number of threads in the pool.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is 8.
         */
        public int getCoreSize();
        public void setCoreSize(int coreSize);

        /**
         * Maximum allowed number of threads.
         * If tasks are filling up the queue, the pool can expand up to this size.
         * Ignored if the queue is unbounded.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is Integer.MAX_VALUE.
         */
        public int getMaxSize();
        public void setMaxSize(int maxSize);

        /**
         * Whether core threads are allowed to time out.
         * This enables dynamic growing and shrinking of the pool.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is true.
         */
        public boolean isAllowCoreThreadTimeout();
        public void setAllowCoreThreadTimeout(boolean allowCoreThreadTimeout);

        /**
         * Time limit for which threads may remain idle before being terminated.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is 60 seconds.
         */
        public Duration getKeepAlive();
        public void setKeepAlive(Duration keepAlive);

        /**
         * Get shutdown configuration for the pool.
         */
        public Shutdown getShutdown();

        public static class Shutdown {
            /**
             * Whether to accept further tasks after the application context close phase has begun.
             * Default is false.
             */
            public boolean isAcceptTasksAfterContextClose();
            public void setAcceptTasksAfterContextClose(boolean acceptTasksAfterContextClose);
        }
    }

    /**
     * Shutdown configuration for task executor.
     */
    public static class Shutdown {
        /**
         * Whether the executor should wait for scheduled tasks to complete on shutdown.
         * Default is false.
         */
        public boolean isAwaitTermination();
        public void setAwaitTermination(boolean awaitTermination);

        /**
         * Maximum time the executor should wait for remaining tasks to complete.
         * Null means wait indefinitely.
         */
        public Duration getAwaitTerminationPeriod();
        public void setAwaitTerminationPeriod(Duration awaitTerminationPeriod);
    }

    /**
     * Mode determining when the task executor is to be created.
     */
    public enum Mode {
        /**
         * Create the task executor if no user-defined executor is present.
         */
        AUTO,

        /**
         * Create the task executor even if a user-defined executor is present.
         */
        FORCE
    }
}

Configuration Example

spring:
  task:
    execution:
      mode: auto
      thread-name-prefix: "app-task-"
      pool:
        core-size: 4
        max-size: 16
        queue-capacity: 100
        keep-alive: 30s
        allow-core-thread-timeout: true
        shutdown:
          accept-tasks-after-context-close: false
      shutdown:
        await-termination: true
        await-termination-period: 60s

Task Scheduling Configuration

TaskSchedulingProperties

Configuration properties for task scheduling with ThreadPoolTaskScheduler.

@ConfigurationProperties("spring.task.scheduling")
public class TaskSchedulingProperties {
    /**
     * Get pool configuration.
     */
    public Pool getPool();

    /**
     * Get simple configuration.
     */
    public Simple getSimple();

    /**
     * Get shutdown configuration.
     */
    public Shutdown getShutdown();

    /**
     * Prefix to use for the names of newly created threads.
     * Default is "scheduling-".
     */
    public String getThreadNamePrefix();
    public void setThreadNamePrefix(String threadNamePrefix);

    /**
     * Pool configuration for scheduled task executor.
     */
    public static class Pool {
        /**
         * Maximum allowed number of threads.
         * Doesn't have an effect if virtual threads are enabled.
         * Default is 1.
         */
        public int getSize();
        public void setSize(int size);
    }

    /**
     * Simple configuration for lightweight scheduled task execution.
     */
    public static class Simple {
        /**
         * Set the maximum number of parallel accesses allowed.
         * -1 indicates no concurrency limit at all.
         * Null means no limit is set.
         */
        public Integer getConcurrencyLimit();
        public void setConcurrencyLimit(Integer concurrencyLimit);
    }

    /**
     * Shutdown configuration for task scheduler.
     */
    public static class Shutdown {
        /**
         * Whether the executor should wait for scheduled tasks to complete on shutdown.
         * Default is false.
         */
        public boolean isAwaitTermination();
        public void setAwaitTermination(boolean awaitTermination);

        /**
         * Maximum time the executor should wait for remaining tasks to complete.
         * Null means wait indefinitely.
         */
        public Duration getAwaitTerminationPeriod();
        public void setAwaitTerminationPeriod(Duration awaitTerminationPeriod);
    }
}

Configuration Example

spring:
  task:
    scheduling:
      thread-name-prefix: "scheduler-"
      pool:
        size: 2
      shutdown:
        await-termination: true
        await-termination-period: 30s

Usage Examples

Async Task Execution

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAsync
public class AsyncConfiguration {
    // Async support enabled
}

@Service
public class EmailService {

    @Async
    public void sendEmail(String to, String subject, String body) {
        // This method runs asynchronously in the configured task executor
        System.out.println("Sending email to " + to + " in thread: " +
                         Thread.currentThread().getName());
        // Email sending logic
    }

    @Async
    public CompletableFuture<String> processWithResult() {
        // Async method that returns a result
        String result = performLongRunningTask();
        return CompletableFuture.completedFuture(result);
    }

    private String performLongRunningTask() {
        // Long-running task logic
        return "Task completed";
    }
}

Scheduled Tasks

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableScheduling
public class SchedulingConfiguration {
    // Scheduling support enabled
}

@Component
public class ScheduledTasks {

    @Scheduled(fixedRate = 5000)
    public void performTask() {
        System.out.println("Task executed every 5 seconds in thread: " +
                         Thread.currentThread().getName());
    }

    @Scheduled(cron = "0 0 * * * *")
    public void hourlyTask() {
        System.out.println("Hourly task executed");
    }

    @Scheduled(fixedDelay = 10000, initialDelay = 5000)
    public void delayedTask() {
        System.out.println("Task with fixed delay and initial delay");
    }
}

Custom Executor Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.Executor;

@Configuration
public class TaskConfiguration {

    @Bean(name = "customTaskExecutor")
    public Executor customTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix("custom-exec-");
        executor.initialize();
        return executor;
    }

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(3);
        scheduler.setThreadNamePrefix("custom-scheduler-");
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        scheduler.setAwaitTerminationSeconds(30);
        scheduler.initialize();
        return scheduler;
    }
}

@Service
public class ServiceWithCustomExecutor {

    @Async("customTaskExecutor")
    public void executeWithCustomExecutor() {
        System.out.println("Running in custom executor: " +
                         Thread.currentThread().getName());
    }
}

Complete Configuration Example

spring:
  task:
    execution:
      # Execution mode
      mode: auto  # or 'force' to create even if user-defined executor exists

      # Thread naming
      thread-name-prefix: "myapp-task-"

      # Simple executor settings (lightweight alternative)
      simple:
        concurrency-limit: 10
        cancel-remaining-tasks-on-close: false
        reject-tasks-when-limit-reached: true

      # Pool executor settings (default executor type)
      pool:
        core-size: 8
        max-size: 32
        queue-capacity: 1000
        keep-alive: 60s
        allow-core-thread-timeout: true
        shutdown:
          accept-tasks-after-context-close: false

      # Shutdown behavior
      shutdown:
        await-termination: true
        await-termination-period: 120s

    scheduling:
      # Thread naming
      thread-name-prefix: "myapp-scheduler-"

      # Pool settings
      pool:
        size: 4

      # Simple settings (alternative to pool)
      simple:
        concurrency-limit: 5

      # Shutdown behavior
      shutdown:
        await-termination: true
        await-termination-period: 60s

Production Configuration

spring:
  task:
    execution:
      pool:
        core-size: 16
        max-size: 64
        queue-capacity: 500
        keep-alive: 120s
      shutdown:
        await-termination: true
        await-termination-period: 180s

    scheduling:
      pool:
        size: 8
      shutdown:
        await-termination: true
        await-termination-period: 90s

Testing Configuration

spring:
  task:
    execution:
      pool:
        core-size: 2
        max-size: 4
        queue-capacity: 10
      shutdown:
        await-termination: true
        await-termination-period: 5s

    scheduling:
      pool:
        size: 1
      shutdown:
        await-termination: true
        await-termination-period: 5s

Advanced Usage with Error Handling

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import java.util.concurrent.Executor;

@Configuration
public class AsyncExceptionHandlingConfiguration implements AsyncConfigurer {

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, params) -> {
            System.err.println("Exception in async method: " + method.getName());
            System.err.println("Exception message: " + throwable.getMessage());
        };
    }
}

@Service
public class RobustTaskService {
    private static final Logger logger = LoggerFactory.getLogger(RobustTaskService.class);

    @Async
    public void executeWithErrorHandling() {
        try {
            // Task logic that might throw exceptions
            performRiskyOperation();
        } catch (Exception e) {
            logger.error("Error in async task", e);
            // Handle or rethrow
        }
    }

    @Scheduled(fixedRate = 60000)
    public void scheduledTaskWithErrorHandling() {
        try {
            // Scheduled task logic
            performScheduledOperation();
        } catch (Exception e) {
            logger.error("Error in scheduled task", e);
            // Continue running on next schedule
        }
    }

    private void performRiskyOperation() {
        // Implementation
    }

    private void performScheduledOperation() {
        // Implementation
    }
}

Monitoring Task Execution

import org.springframework.boot.actuate.metrics.AutoTimer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;

@Service
public class MonitoredTaskService {
    private final MeterRegistry meterRegistry;
    private final Timer taskTimer;

    public MonitoredTaskService(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.taskTimer = Timer.builder("async.task.execution")
            .description("Async task execution time")
            .register(meterRegistry);
    }

    @Async
    public void monitoredTask() {
        taskTimer.record(() -> {
            // Task execution
            performWork();
        });
    }

    private void performWork() {
        // Implementation
    }
}

Best Practices

Thread Pool Sizing

# For CPU-bound tasks
spring:
  task:
    execution:
      pool:
        core-size: ${NUMBER_OF_PROCESSORS}  # Match CPU cores
        max-size: ${NUMBER_OF_PROCESSORS}
        queue-capacity: 100

# For I/O-bound tasks
spring:
  task:
    execution:
      pool:
        core-size: ${NUMBER_OF_PROCESSORS * 2}
        max-size: ${NUMBER_OF_PROCESSORS * 4}
        queue-capacity: 500

Graceful Shutdown

spring:
  task:
    execution:
      shutdown:
        await-termination: true
        await-termination-period: 120s  # Allow time for tasks to complete
    scheduling:
      shutdown:
        await-termination: true
        await-termination-period: 60s

Environment-Specific Configuration

# application-dev.yml
spring:
  task:
    execution:
      pool:
        core-size: 2
        max-size: 4

# application-prod.yml
spring:
  task:
    execution:
      pool:
        core-size: 16
        max-size: 64

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-autoconfigure

docs

index.md

tile.json