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

Spring 6.1.3 to 6.2.2 initialization circularity? #34308

Open
mebigfatguy opened this issue Jan 22, 2025 · 3 comments
Open

Spring 6.1.3 to 6.2.2 initialization circularity? #34308

mebigfatguy opened this issue Jan 22, 2025 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@mebigfatguy
Copy link
Contributor

Unable to find Spring bean for class com.acme.pgbu.services.workflow.event.WorkflowAlertExecutorActor in application Anvil
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'workflowAlertExecutorActor': Unsatisfied dependency expressed through field 'm_alertStartWorkflowService': Error creating bean with name 'alertStartWorkflowService': Requested bean is currently in creation: Is there an unresolvable circular reference or an asynchronous initialization dependency?

I see other reports of this, but they are pretty useless at least generally, so rather than trying to solve my problem, can i get some general ideas?

  • Is the circularity always between the two classes mentioned in the exception?
  • Is there a way to get some -debug printout of the spring dependency tree that caused the exception?
  • If the child is autowired into the parent as a field, does this imply that the child was created by one of the parents of the first? And so rearranging the grandparents fields may resolve this?
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 22, 2025
@jhoeller
Copy link
Contributor

Our intended difference between 6.1.x and 6.2.x is primarily in locking around concurrent initialization scenarios. If you are seeing such "currently in creation" exceptions, it means that some other thread started initializing a specific bean before the main initialization thread also reaches that bean. In a single-threaded startup scenario, this should never happen even in 6.2. In a multi-threaded startup scenario, 6.2 selectively applies lenient locking instead of strict locking which is where those effects can start showing. I am primarily interested in understanding where those other threads come from. Common Spring application startup is single-threaded, it was never meant to have uncontrolled initialization threads being in competition with each other. If we understand those scenarios better, we can try to revise the impact on such scenarios in 6.2.3.

Last but not least, there could also be a regression in circularity handling in a single-threaded startup scenario. If so, we'd also need to specifically understand where that is coming from.

@jhoeller jhoeller added the in: core Issues in core modules (aop, beans, core, context, expression) label Jan 22, 2025
@jhoeller jhoeller self-assigned this Jan 22, 2025
@mebigfatguy
Copy link
Contributor Author

OK, so this is the async case, and not circularity then. Good to know. These beans are pekko actors, so potentially there is some threading going on, altho i'll have to dive in.

I guess the problem is can I add debugging that show what thread these initializations are on? Probably not right?, as i'm guessing when you detect this situation, it's not my code that is running.

@jhoeller
Copy link
Contributor

There may be some circularity involved but not necessarily so. In an async case, the main thread might start initializing a certain bean and its transitive dependencies, while another thread starts initializing one of those same dependencies shortly before the main thread gets to it. As of 6.2.2, it is fine the other way round (the main thread starting to initialize a bean and then an async thread trying to initializing the same bean) since the singleton lock is primarily owned by the main thread, but if an async thread gets in the way of the main initialization thread while the main thread holds the singleton lock, there is a potential for "currently in creation" exceptions. We'll try to refine this in 6.2.3 for specific scenarios as we learn to understand them.

You could turn on debug logging for org.springframework.beans and add the thread name to the log line through logger configuration. This should reveal everything you need to see.

The common solution is to force early initialization in the main startup thread before other threads are allowed to hit the bean factory. In a typical Servlet setup, this happens through a distinct context initialization phase which has to be completed before requests are allowed to hit the context. In an actor application, you should ideally defer the start of the actor system until the Spring application context and its bean factory have completed their initialization phase (ConfigurableApplicationContext.refresh() having returned), or at least until all the common beans have been initialized (possibly through @DependsOn declarations on the bean that starts the actor system, forcing the initialization of all relevant beans in the main thread first).

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: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

4 participants