{"id":"08f29af12af7c707","repo":"spring-projects/spring-framework","slug":"beanfactory-must-be-set-on-getclass-getsimplena","errorCode":null,"errorMessage":"BeanFactory must be set on {getClass().getSimpleName()} to access qualified executor '{qualifier}'","messagePattern":"BeanFactory must be set on (.+?) to access qualified executor '(.+?)'","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java","lineNumber":214,"sourceCode":"\t * been specified and that the {@linkplain #setExecutor(Executor) default executor}\n\t * should be used.\n\t * @param method the method to inspect for executor qualifier metadata\n\t * @return the qualifier if specified, otherwise empty String or {@code null}\n\t * @see #determineAsyncExecutor(Method)\n\t * @see #findQualifiedExecutor(BeanFactory, String)\n\t */\n\tprotected abstract @Nullable String getExecutorQualifier(Method method);\n\n\t/**\n\t * Retrieve a target executor for the given qualifier.\n\t * @param qualifier the qualifier to resolve\n\t * @return the target executor, or {@code null} if none available\n\t * @since 4.2.6\n\t * @see #getExecutorQualifier(Method)\n\t */\n\tprotected @Nullable Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, String qualifier) {\n\t\tif (beanFactory == null) {\n\t\t\tthrow new IllegalStateException(\"BeanFactory must be set on \" + getClass().getSimpleName() +\n\t\t\t\t\t\" to access qualified executor '\" + qualifier + \"'\");\n\t\t}\n\t\treturn BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);\n\t}\n\n\t/**\n\t * Retrieve or build a default executor for this advice instance.\n\t * <p>An executor returned from here will be cached for further use.\n\t * <p>The default implementation searches for a unique {@link TaskExecutor} bean\n\t * in the context, or for an {@link Executor} bean named \"taskExecutor\" otherwise.\n\t * If neither of the two is resolvable, this implementation will return {@code null}.\n\t * @param beanFactory the BeanFactory to use for a default executor lookup\n\t * @return the default executor, or {@code null} if none available\n\t * @since 4.2.6\n\t * @see #findQualifiedExecutor(BeanFactory, String)\n\t * @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME\n\t */\n\tprotected @Nullable Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java#L196-L232","documentation":"Thrown by findQualifiedExecutor when an async method carries an executor qualifier (e.g. @Async(\"customExecutor\")) but the aspect's BeanFactory was never injected. Resolving a qualified executor requires a BeanFactory to look the bean up by type+qualifier; without one the lookup cannot proceed. The class name in the message is the concrete aspect subclass (AnnotationAsyncExecutionInterceptor, an AspectJ aspect, etc.).","triggerScenarios":"Invoking an @Async method whose qualifier is non-empty while the AsyncExecutionAspectSupport instance was built programmatically and never had setBeanFactory(BeanFactory) called. Also fires when an AnnotationAsyncExecutionAspect (AspectJ) is woven but not registered as a Spring bean.","commonSituations":"Manually new-ing an AsyncExecutionInterceptor/Aspect instead of letting <task:annotation-driven/> or @EnableAsync wire it; using AspectJ load-time weaving for @Async without the Spring container managing the aspect; qualifier typo that still resolves to a non-empty string.","solutions":["Register the async aspect/interceptor as a Spring bean so the container invokes setBeanFactory automatically (e.g. via @EnableAsync or <task:annotation-driven/>).","If constructing programmatically, call aspect.setBeanFactory(applicationContext) explicitly before any async invocation.","Drop the qualifier from @Async so the default-executor path (which does not need a BeanFactory) is used, or pass a concrete Executor to setExecutor()."],"exampleFix":"// before\nAsyncExecutionInterceptor aspect = new AsyncExecutionInterceptor();\nadvisor = new DefaultPointcutAdvisor(pointcut, aspect);\n// beanFactory never set -> error 100 on @Async(\"poolA\")\n\n// after\nAsyncExecutionInterceptor aspect = new AsyncExecutionInterceptor();\naspect.setBeanFactory(applicationContext);\nadvisor = new DefaultPointcutAdvisor(pointcut, aspect);","handlingStrategy":"validation","validationCode":"// before relying on a qualified executor, confirm the aspect has a BeanFactory\nif (aspect instanceof BeanFactoryAware && applicationContext != null) {\n    aspect.setBeanFactory(applicationContext);\n}\n// or, when scanning for @Async qualifiers, ensure the owning bean is Spring-managed:\nboolean managed = applicationContext.containsBeanDefinition(beanName);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always register async aspects/interceptors as Spring beans instead of constructing them with new.","Enable @Async through @EnableAsync or <task:annotation-driven/> so setBeanFactory runs automatically.","Document that any @Async qualifier requires a Spring-managed aspect."],"tags":["spring-aop","async","executor","beanfactory","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}