Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DefaultListableBeanFactory#getSingletonFactoryBeanForTypeCheck deadlock #30887

Closed
msangel opened this issue Jul 14, 2023 · 2 comments
Closed
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue

Comments

@msangel
Copy link

msangel commented Jul 14, 2023

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)
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 14, 2023
@jhoeller
Copy link
Contributor

jhoeller commented Jul 14, 2023

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.

@jhoeller jhoeller added status: duplicate A duplicate of another issue in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jul 14, 2023
@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Jul 14, 2023
@msangel
Copy link
Author

msangel commented Jul 14, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

4 participants