๐Ÿ”ด The Error You're Seeing

Confirm this matches your console output. If it does, you're in the right place.

ERROR LOGorg.springframework.scheduling.annotation.AsyncConfigurationException: No AsyncConfigurer found. at org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor.setBeanFactory(AsyncAnnotationBeanPostProcessor.java:123)

โšก Quick Fix Works 80% of the time

Add @EnableAsync to your main Application class or a @Configuration class.

@SpringBootApplication @EnableAsync public class Application { ... }

๐Ÿง  Why this Happens

Tap to expand the deep technical explanation

You used the @Async annotation, but Spring's asynchronous execution infrastructure is either not enabled (missing @EnableAsync) or misconfigured. Without an AsyncConfigurer, Spring doesn't know which thread pool to use to execute the background task.

The HITEC City Parking Spot Analogy:

Imagine a restaurant manager asking a waiter to clean tables, but the manager never hired a cleaning staff (Thread Pool). The waiter has to clean the tables themselves, blocking the main dining room.

๐Ÿ” How to Reproduce Confirm this is your error

Annotate a method with @Async but forget to add @EnableAsync, then call it. Spring throws AsyncConfigurationException: No AsyncConfigurer found.

๐Ÿ› ๏ธ Solutions (3 Ways to Fix)

Solution 1โœ“ Most common cause

Add @EnableAsync annotation

๐Ÿ‘‰ Use this if your @Async methods are running synchronously or throwing config errors.

Spring Boot does not enable asynchronous processing by default. You must explicitly turn it on with @EnableAsync.

@SpringBootApplication @EnableAsync // Add this public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Solution 2

Implement AsyncConfigurer interface

๐Ÿ‘‰ Use this if you want to define a custom thread pool or exception handler.

Create a configuration class that implements AsyncConfigurer to gain fine-grained control over how @Async tasks are executed.

@Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.initialize(); return executor; } }
Solution 3

Avoid self-invocation

๐Ÿ‘‰ Use this if @EnableAsync is present but the method still runs synchronously.

Spring's @Async uses a proxy. If you call an @Async method from another method in the SAME class, the proxy is bypassed, and it runs synchronously. Inject the bean into itself.

@Service public class ReportService { @Autowired private ReportService self; // Inject self public void generate() { self.generateAsync(); // Calls through proxy } @Async public void generateAsync() { ... } }

๐Ÿ“‹ Version Notes

Spring Boot 2.x

Uses SimpleAsyncTaskExecutor by default if no custom pool is defined.

Spring Boot 3.x

Requires explicit configuration for robust production use.

๐Ÿ›ก๏ธ How to Prevent This Next Time

Always create a custom ThreadPoolTaskExecutor bean when using @Async in production to prevent unbounded thread creation.

Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase