Very rarely my application run fails with following error:
[main] ERROR o.s.boot.SpringApplication - Application run failed
java.util.NoSuchElementException: null
at java.base/java.util.ArrayDeque.removeFirst(Unknown Source)
at org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup.record(BufferingApplicationStartup.java:138)
at org.springframework.boot.context.metrics.buffering.BufferedStartupStep.end(BufferedStartupStep.java:92)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:614)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
Spring boot version is 2.4.1. I have following spring-related dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
Comment From: bclozel
Unfortunately, this doesn't provide enough information to figure this problem out.
This should only happen if startup events during the the context refresh happen concurrently; this should not happen since the context refresh is single threaded. I'd be interested to have more clues about this instance.
- Are there
ApplicationRunner
instances or application beans doing multi-threaded work during their initialization? - Did you set a specific value for
spring.data.jpa.repositories.bootstrap-mode
?
I'm not really optimistic here, since reproducing this issue is really hard by definition. But we can repurpose this issue to explore ways to mitigate this problem or provide more useful information in case of failures.
Comment From: IvanPavlov1995
I didn't set a specific value for spring.data.jpa.repositories.bootstrap-mode
. I don't think I have ApplicationRunner
instances with such logic but regular beans could do multi-threaded work. This project is quite large so I'm not sure I can find the root cause. It would be great if you could point me where exactly I can check something you need to investigate that
Comment From: philwebb
I wonder if BufferedStartupStep.end()
is somehow being called twice? Perhaos we should change currentSteps.removeFirst
to instead remove the BufferedStartupStep.id
?
Comment From: IvanPavlov1995
Actually I can't be sure, but I don't use it manually or something like that. I just added application runner into existing application upon migration on spring boot 2.4.1 from 2.3.x.
Comment From: philwebb
As a first step we're going to try and add some more logging
Comment From: gbrehmer
We have the same problem (Spring Boot 2.4.5), probably produced by heavy use of custom request scope beans
java.util.NoSuchElementException: null
at java.base/java.util.ArrayDeque.removeFirst(Unknown Source)
at org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup.record(BufferingApplicationStartup.java:138)
at org.springframework.boot.context.metrics.buffering.BufferedStartupStep.end(BufferedStartupStep.java:92)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:394)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:676)
we initialize the Startup Bean with:
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationStartup(new BufferingApplicationStartup(10000));
Comment From: philwebb
@gbrehmer I don't suppose you're able to replicate the issue in a small sample application?
Comment From: gbrehmer
sorry, not that easy, I tried a concurrent MockMVC Test but can not reproduce the issue. Probably because context startup inside junit tests differs to a normal application startup.
Currently ArrayDeque
is used, which is not thread-safe. So what about using a thread-safe Deque
variant?
Comment From: bclozel
Arguably we should not track startup metrics for request-scoped beans - the application is already started and this was not designed to be used continuously at runtime. Maybe we should stop tracking things once the context is fully refreshed? This might limit issues like this but could also miss important data. This would be handled at the Spring Framework level.
@gbrehmer this feature is about tracking the context startup, which is single-threaded. We've chosen this variant to avoid performance overhead when measuring.
Comment From: gbrehmer
@gbrehmer this feature is about tracking the context startup, which is single-threaded. We've chosen this variant to avoid performance overhead when measuring.
I know what this feature is about, but I don't know which dependencies exists or how the lifecycle is intercepted. From my perspective this should be fixed soon and probably by excluding request scope beans (I would assume that there is no request scope bean in creation during startup)
Comment From: bharatnpti
@philwebb - we are also facing same issue with Spring Boot version 2.4.4 Do we have any plan to back port it or some temporary fix for older versions.
Comment From: bclozel
@bharatnpti it's been fixed in 2.4.6.
Comment From: bharatnpti
@bclozel - yes I saw that but we are using 2.4.4 presently, so I guess only option is to move to 2.4.6 if not backported
Comment From: snicoll
@bharatnpti 2.4.6
is a patch release of 2.4.4
. The last in this line is 2.4.13
. There's no such thing as "backporting" on the same line.