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

Change of behaviour in the beans loading order #1965

Closed
jorgerod opened this issue Nov 28, 2022 · 4 comments · Fixed by #1969
Closed

Change of behaviour in the beans loading order #1965

jorgerod opened this issue Nov 28, 2022 · 4 comments · Fixed by #1969
Labels
enhancement New feature or request

Comments

@jorgerod
Copy link

Describe the bug

Hello

I wanted to tell you about the problem I am having. The problem is unusual and will not happen easily.

The BeanFactoryPostProcessors SpringdocBeanFactoryConfigurer and SpringdocActuatorBeanFactoryConfigurer are causing a change in the loading order in an application I have with springdoc and spring-cloud-stream when there is a pollable and it is causing an error.

ConfigurableListableBeanFactory#getBeanNamesForType(Class) method is causing factorybeans to be initialised.

public static void initBeanFactoryPostProcessor(ConfigurableListableBeanFactory beanFactory) {
for (String beanName : beanFactory.getBeanNamesForType(OpenAPIService.class))
beanFactory.getBeanDefinition(beanName).setScope(SCOPE_PROTOTYPE);
for (String beanName : beanFactory.getBeanNamesForType(OpenAPI.class))
beanFactory.getBeanDefinition(beanName).setScope(SCOPE_PROTOTYPE);

Internally this call is being made:

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type) {
		return getBeanNamesForType(type, true, true);
	}

And according to the javadoc of ListableBeanFactory, the third parameter can cause dangerous behaviour.

allowEagerInit – whether to initialize lazy-init singletons and objects created by FactoryBeans (or by factory methods with a "factory-bean" reference) for the type check. Note that FactoryBeans need to be eagerly initialized to determine their type: So be aware that passing in "true" for this flag will initialize FactoryBeans and "factory-bean" references.

In my case, BindableFunctionProxyFactory (implements FactoryBean) is being initialised early and internally doing

	protected void populateBindingTargetFactories(BeanFactory beanFactory) {
		this.bindingTargetFactories = ((ListableBeanFactory) beanFactory).getBeansOfType(BindingTargetFactory.class);
	}

. But as it is initialised early, it will not load all the beans it should. That is, the FactoryBean is created without guaranteeing that all the beans have already been created.

To Reproduce
Steps to reproduce the behavior:

  • What version of spring-boot you are using? 2.7.6
  • What modules and versions of springdoc-openapi are you using? It happens with both springdoc-webmvc and springdoc-webflux.
  • What version of springdoc you are using? 1.5.x, 1.6.x and 2.0.0
  • Occurs with springdoc.show-actuator=true and managemente.port different.

Solution

This problem can easily be solved in the following way

In SpringdocBeanFactoryConfigurer class, get beans by type with allowEagerInit flag set to false

  /**
   * Init bean factory post processor.
   *
   * @param beanFactory the bean factory
   */
  public static void initBeanFactoryPostProcessor(final ConfigurableListableBeanFactory beanFactory) {
    for (final String beanName : beanFactory.getBeanNamesForType(OpenAPIService.class, true, false)) {
      beanFactory.getBeanDefinition(beanName).setScope(SCOPE_PROTOTYPE);
    }
    for (final String beanName : beanFactory.getBeanNamesForType(OpenAPI.class, true, false)) {
      beanFactory.getBeanDefinition(beanName).setScope(SCOPE_PROTOTYPE);
    }
  }

In fact, I can make a contribution if you like.

@bnasslahsen
Copy link
Collaborator

@jorgerod,

You are welcome to propose a Pr with the related unit tests for this enhancement

@bnasslahsen bnasslahsen added the enhancement New feature or request label Nov 28, 2022
jorgerod added a commit to jorgerod/springdoc-openapi that referenced this issue Nov 29, 2022
bnasslahsen added a commit that referenced this issue Nov 29, 2022
…ry-configurer

Prevents premature initialisation of factory-beans. Fixes #1965
@jorgerod
Copy link
Author

jorgerod commented Dec 1, 2022

@bnasslahsen Is there a release date for the new 1.6.x version?

This is a very important version for us.

Thank you very much and sorry for the inconvenience

@bnasslahsen
Copy link
Collaborator

@jorgerod,

Not yet planned. When you say this is very important for us.
Can you be more specific. Who is the us?

@jorgerod
Copy link
Author

jorgerod commented Dec 5, 2022

Hi @bnasslahsen

We have a Spring-boot based framework that uses OpenApi contracts and we support SpringDoc to use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants