Skip to content

BeanCurrentlyInCreationException with DelegatingWebFluxConfiguration #25166

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

Open
rwinch opened this issue May 29, 2020 · 1 comment
Open

BeanCurrentlyInCreationException with DelegatingWebFluxConfiguration #25166

rwinch opened this issue May 29, 2020 · 1 comment
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement

Comments

@rwinch
Copy link
Member

rwinch commented May 29, 2020

DelegatingWebFluxConfiguration can trigger BeanCurrentlyInCreationException under a few circumstances.

ReactiveAdapterRegistry

The first problem is that it is difficult to provide a HandlerMethodArgumentResolver that needs the ReactiveAdapterRegistry because this can cause a cycle depending on the order the beans are instantiated. For example, this test produces a cycle:

  1. authenticationPrincipalArgumentResolver is requested
  2. It triggers the creation of ReactiveAdapterRegistry which is a dependant bean
  3. In order to create ReactiveAdapterRegistry, DelegatingWebFluxConfiguration needs to be created which requires all WebFluxConfigurer instances to be wired into it.
  4. This tries to retrieve all WebFluxConfigurer instances. One of which is authenticationPrincipalArgumentResolverConfigurer which provides our authenticationPrincipalArgumentResolver bean as an argument resolver.
  5. This requests authenticationPrincipalArgumentResolver which is a cycle

One option to make this less likely to happen is to define authenticationPrincipalArgumentResolverConfigurer as:

@Bean
public WebFluxConfigurer authenticationPrincipalArgumentResolverConfigurer(
		ObjectProvider<AuthenticationPrincipalArgumentResolver> authenticationPrincipalArgumentResolver) {
	return new WebFluxConfigurer() {
		@Override
		public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
			configurer.addCustomResolver(authenticationPrincipalArgumentResolver.getObject());
		}
	};
}

This delays the lookup of AuthenticationPrincipalArgumentResolver. However, this has a few drawbacks.

  1. The first drawback is that while it reduces the likelihood of an error, it doesn't remove the cycle between ArgumentResolverConfig and WebFluxConfigurationSupport.
  2. Second, it requires every AuthenticationPrincipalArgumentResolver configuration needing ReactiveAdapterRegistry (I'd argue that is pretty much every AuthenticationPrincipalArgumentResolver) to have the burden of fixing the issue rather than decoupling the beans (HandlerMethodArgumentResolver and ReactiveAdapterRegistry) that are likely dependant on one another).

We could move the delay inside DelegatingWebFluxConfiguration by autowiring ObjectProvider<WebFluxConfigurer> instead. However, this only fixes the second problem and leaves the cycle present.

Another option is to make the definition of ReactiveAdapterRegistry a static method. This would ensure that DelegatingWebFluxConfiguration does not need to be instantiated. Yet another option would be to move ReactiveAdapterRegistry to another configuration, but this could break other applications.

ResourceUrlProvider Can Cause Early Initialization of DelegatingWebFluxConfiguration

ResourceUrlProvider implements ApplicationListener which can trigger early initialization of DelegatingWebFluxConfiguration. As soon as an ApplicationEvent is published, the ApplicationListeners need initialized. Since ResourceUrlProvider is defined by DelegatingWebFluxConfiguration it initializes DelegatingWebFluxConfiguration and all of its dependant beans very early on.

This is what is why the originally reported issue would happen in Boot 2.3.0 and not in previous versions. Specifically the changes for spring-projects/spring-boot#21325 moved the publishing of the ReactiveWebServerInitializedEvent from finishRefresh to SmartLifecycle's start method. This changed the order that DelegatingWebFluxConfiguration was created and triggered the bean cycle to happen.

One solution is to move the ResourceUrlProvider bean definition to a static method.

Related Issues

@THS-on
Copy link

THS-on commented Sep 5, 2020

We currently run into this issue. Is there a workaround that we could apply?

It seems that it's really inconsistent when it happens. gradle bootRun always works but building a jar and starting it works on one machine and fails on on others.

Gradle config versions

id("org.springframework.boot") version "2.3.3.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.3.72"
kotlin("plugin.spring") version "1.3.72"

@rstoyanchev rstoyanchev self-assigned this Jun 7, 2022
@rstoyanchev rstoyanchev added this to the Triage Queue milestone Jun 7, 2022
@bclozel bclozel added the type: enhancement A general enhancement label Jun 7, 2022
@bclozel bclozel removed this from the Triage Queue milestone Jan 17, 2023
@jhoeller jhoeller added status: waiting-for-triage An issue we've not yet triaged or decided on and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 17, 2024
@jhoeller jhoeller added this to the 6.x Backlog milestone Jan 23, 2024
@jhoeller jhoeller modified the milestones: 6.x Backlog, General Backlog Oct 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants