Affects: 6.0.7

I have multiple beans than are invoking JPA repositories in @PostConstruct methods. Those JPA entities are invoked in delayed executors (Executors.newSingleThreadExecutor). Having more then one such code cause entire application deadlock of two treads with this stack:

getSingletonFactoryBeanForTypeCheck:973, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getTypeForFactoryBean:892, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
isTypeMatch:619, AbstractBeanFactory (org.springframework.beans.factory.support)
doGetBeanNamesForType:573, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBeanNamesForType:540, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBeanNamesForType:526, DefaultListableBeanFactory (org.springframework.beans.factory.support)
beanNamesForTypeIncludingAncestors:225, BeanFactoryUtils (org.springframework.beans.factory)
qualifiedBeanOfType:118, BeanFactoryAnnotationUtils (org.springframework.beans.factory.annotation)
qualifiedBeanOfType:95, BeanFactoryAnnotationUtils (org.springframework.beans.factory.annotation)
determineQualifiedTransactionManager:518, TransactionAspectSupport (org.springframework.transaction.interceptor)
determineTransactionManager:496, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:345, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:119, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:184, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:137, PersistenceExceptionTranslationInterceptor (org.springframework.dao.support)
proceed:184, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:134, CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor (org.springframework.data.jpa.repository.support)
proceed:184, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:97, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:184, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:218, JdkDynamicAopProxy (org.springframework.aop.framework)
findAllC5:-1, $Proxy178 (jdk.proxy4)
reloadCache:89, AvailableCache (com.ecma.cache)
lambda$init$0:75, AvailableCache (com.ecma.cache)
run:-1, AvailableCache$$Lambda$1390/0x0000000801c34f90 (com.ecma.cache)
call:539, Executors$RunnableAdapter (java.util.concurrent)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
runWorker:1136, ThreadPoolExecutor (java.util.concurrent)
run:635, ThreadPoolExecutor$Worker (java.util.concurrent)
run:833, Thread (java.lang)

Comment From: jhoeller

This is a duplicate of #25074. As mentioned there, for such a scenario, your bean should either implement SmartInitializingSingleton.afterSingletonsInstantiated() or rely on the context refresh event: ApplicationListener<ContextRefreshedEvent> or @EventListener(ContextRefreshedEvent.class).

Those phases are meant for post-initialization work outside of any container lock, whereas @PostConstruct (like InitializingBean.afterPropertiesSet()) is part of the individual instantiation phase of each bean. As a consequence, the bean instance is only considered as fully initialized and ready to be published to others after returning from its @PostConstruct method. In the end, @PostConstruct is only really meant for validating the configuration state and possibly preparing some data structures based on the given configuration but no further activity.

We are aware of the unpleasant deadlock potential but cannot straightforwardly prevent custom Executor usage in @PostConstruct upfront. All we can do is to prominently document this as part of #25074.

Comment From: msangel

Thanks for the reply! I solved this for myself by initiating a thread once at least one consumed item come for a process by it.

And some offtopic question: Are there any templated beans that allow continuous work? Like listening for events and reacting on them, where the executor will be a parameter?