Skip to content

Skip lazy initialization of beans that explicitly set the lazy attribute to false #16184

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

Closed
jhaeyaert opened this issue Mar 9, 2019 · 10 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@jhaeyaert
Copy link

Hi,

The suspected issue described below is related to the version 2.2.0.M1 of Spring Boot.

It appears that the management endpoints are not reachable when using the new lazy initialization feature with actuator endpoints exposed on another port than the default one.

Steps to reproduce :

  • Create a new project from spring initializr with the new Spring Boot 2.2.0.M1 version
  • Add Reactive Web and Actuator dependencies
  • Set the properties management.server.port=8081 and spring.main.lazy-initialization=true

Hit the endpoint http://localhost:8081/actuator/health and you'll get a connection refused.

Switch off the lazy initialization and the actuator endpoints will be back again.
Note that actuator endpoints are working correctly if I switch on the lazy initialization and do not change the management port.

Is something I didn't understand or is there a little bug in the lazy initialization feature ?

By the way, thank you for this feature that I have been waiting for a long time!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 9, 2019
@wilkinsona
Copy link
Member

Thanks for trying out the milestone. This sounds like a bug to me. We caught a similar one that switched off DevTools restart just before we released but this one slipped through.

@wilkinsona wilkinsona added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 9, 2019
@wilkinsona wilkinsona added this to the 2.2.x milestone Mar 9, 2019
@wilkinsona
Copy link
Member

Adding the following bean to your app should work around the problem for now:

@Bean
static BeanFactoryPostProcessor ensureEagerManagementServerInitializationPostProcessor() {
	return (beanFactory) -> {
		String namePrefix = ManagementContextAutoConfiguration.class.getName() + "$";
		for (String definitionName : beanFactory.getBeanDefinitionNames()) {
			if (definitionName.startsWith(namePrefix)) {
				beanFactory.getBeanDefinition(definitionName).setLazyInit(false);
			}
		}
	};
}

This will ensure that the logic that creates the child context for the management server is not lazy and that the server is created and started.

There's a secondary problem here. The beans in the separate management context that's used when the management port does not match the server port are all initialised eagerly. They should be lazy like the main context so that the server is created and listening for requests but, for example, the endpoints are not created until a request is received.

@mbhave mbhave added the for: team-attention An issue we'd like other members of the team to review label Mar 13, 2019
@wilkinsona
Copy link
Member

We're going to explore the possibility of looking at the bean's class via the bean definition or the metadata available from the definition and not setting the lazy init flag if, for example, the bean implements SmartInitializingSingleton.

@wilkinsona wilkinsona removed the for: team-attention An issue we'd like other members of the team to review label Mar 13, 2019
@tkvangorder
Copy link

Is it possible to skip any bean definitions that explicitly set their lazy attribute to false? @Lazy(false)

@philwebb
Copy link
Member

@tkvangorder That's a really nice idea, but I think we might need a framework change to be able to do it. Currently AbstractBeanDefinition.lazyInit is a boolean so we don't know if the value is false because that's the default, or if it's because setLazyInit has been called.

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Mar 14, 2019
@jhoeller
Copy link

We could turn this into a Boolean field indeed and provide a Boolean getLazyInit() accessor on AbstractBeanDefinition... allowing Boot to check whether the flag has been set at all before trying to override it. If this sounds feasible for your purposes, please create a spring-framework issue for it.

@philwebb philwebb added status: blocked An issue that's blocked on an external project change and removed for: team-attention An issue we'd like other members of the team to review labels Mar 27, 2019
@philwebb
Copy link
Member

philwebb commented Apr 2, 2019

spring-projects/spring-framework#22694 is now fixed

@philwebb philwebb removed the status: blocked An issue that's blocked on an external project change label Apr 2, 2019
@mbhave mbhave self-assigned this Apr 5, 2019
mbhave added a commit to mbhave/spring-boot that referenced this issue Apr 5, 2019
mbhave added a commit to mbhave/spring-boot that referenced this issue Apr 5, 2019
@mbhave
Copy link
Contributor

mbhave commented Apr 5, 2019

I've got a fix in a branch here. I was wondering specifically about @wilkinsona's comment

There's a secondary problem here. The beans in the separate management context that's used when the management port does not match the server port are all initialised eagerly. They should be lazy like the main context so that the server is created and listening for requests but, for example, the endpoints are not created until a request is received.

The branch adds a BFPP to the child context for enabling lazy initialization. However, I don't think the creation of endpoints could be delayed till a request is received because of ServletEndpoints. The ServletEndpointRegistrar is a ServletContextInitializer so that will get initialized early in turn causing early initialization of all the endpoints. It's on a branch in case anyone had a different fix in mind for this.

@wilkinsona
Copy link
Member

wilkinsona commented Apr 5, 2019

Thanks for looking at this, @mbhave. There's also a change in DevTools that I made that could perhaps be replaced with some use of @Lazy(false).

For the Actuator child context, I wonder if the problem will be solved without @Lazy(false) if we proceed with #15378. We also talked a bit about trying to detect beans of certain types and not marking them as lazy. That may help with things like Spring Integration's internal components where the user can't add @Lazy(false). Perhaps we should consider that as part of a separate issue though?

The fix that you've made for the laziness in the child context was what I had in mind. I hadn't dug into it in much detail and had only realised that the BFPP was only being applied to the parent context.

@mbhave mbhave changed the title Actuator endpoints with custom port are not reachable when using the new Lazy initialization feature of Spring Boot 2.2.0.M1 Skip lazy initialization of beans that explicitly set the lazy attribute to false Apr 6, 2019
mbhave added a commit that referenced this issue Apr 6, 2019
This commit also adds tests to ensure that the child
management context works when lazy initialization is
enabled. Also, it adds a BeanFactoryPostProcessor to
the child context so that the server is created and
listening for requests but other beans in the child
context are not created until requested.

See gh-16184
@mbhave mbhave closed this as completed in 3c203e9 Apr 6, 2019
@mbhave mbhave modified the milestones: 2.2.x, 2.2.0.M2 Apr 6, 2019
@ghost
Copy link

ghost commented Feb 5, 2020

. That may help with things like Spring Integration's internal components where the user can't add @Lazy(false). Perhaps we should consider that as part of a separate issue though?

Is there a fix for the Spring Integration issue, that would help me resolve issues like the one I am getting here ?

https://stackoverflow.com/questions/60073909/spring-integration-beans-arent-created-when-spring-main-lazy-initialization-tru

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

7 participants