-
Notifications
You must be signed in to change notification settings - Fork 38.4k
Aspect Not Triggered After Restart in Spring Boot 3.4.x (But Works in 3.3.10) #34735
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
Comments
If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem. |
I have finally prepared a sample project as you requested. Here is the GitHub link for your review: |
Thanks. First thing i'd do is to upgrade to the latest Spring Boot 3.4.x version,
I don't see that. A |
Thanks. I also tested with Spring Boot 3.4.4 and manually added |
I can't reproduce it. I've built your application (i had to simplify it, i'm using this) and load-tested it with i've both used IntelliJ for executing as well as |
Sorry, i can now reproduce it. I have increased the concurrency of hey and now i see the stacktrace. |
There's a race condition somewhere. If I start the application, then execute one request with curl, and then start the load test, it works. If i don't execute curl and start the load test right away, it breaks. And it stays broken, even if i try it with curl after stopping the load test. |
Additionally, I've noticed that this issue occurs more frequently when using Oracle DB, when the data already exists in the database and is not inserted during application startup. With H2, it’s much harder to reproduce and happens only occasionally. |
It's nearly identical, but these lines are missing in the failing case:
That's what we can also see on your screenshot. I think this is a bug in spring-aop somewhere. |
I've also tested it with downgraded framework versions 6.2.0 - 6.2.5, and they all have the race condition. |
Interestingly, Boot 3.3.10 with Spring Framework 6.2.5 doesn't fail - so I'm not 100% sure that this is a framework bug. FTR, this is the
and here's the cleaned up application which (most of the time) shows the problem:
|
I'm pretty sure this is not a race condition for aspects specifically. Are there multiple threads trying to obtain beans from the application context during bootstrap? If so, this could be a side effect of lenient locking in 6.2. It's suspicious that Boot 3.3.10 does not fail against Framework 6.2.5 but maybe some differences in Boot just trigger lenient locking in a different way. It is also suspicious that requests reach the application context before it is fully initialized, actually. Note that there is an upcoming revision in 6.2.6 with several lenient locking refinements (avoiding deadlocks), including a @mhalbritter can you reproduce this with your current setup when Boot 3.4.x runs against Framework 6.2.6 snapshot? And specifically, can you reproduce it with |
On a related note, we also got this issue open where the Spring Boot fat jar deployer on IBM Liberty lets requests through to the application context before bootstrap has finished: #34729. While I certainly expect |
It's also reproducible with |
Hmm that's interesting indeed, thanks for checking. Hard to explain then though since it seems to be an initialization problem where the aspect is either applied or not, staying that way for the lifetime of the application. So not an invocation-time race condition, rather a bootstrap-time race condition during creation of the repository beans when the container looks for applicable aspects. Maybe a circular reference resolution problem? So is the application context hit by request threads before the application is officially ready? If yes, how can that happen? With standard |
I think the application is ready. Here are the logs and i waited like 10 seconds before starting the load test:
You can even see the first invocation of the The hibernate SQL statements come from the |
Ok, so even with such a long delay after bootstrap, the problem shows when the load test kicks in immediately - but not when the request code path has been warmed up by an individual request before. Hmm, is any affected bean marked as lazy-init here? Is Spring Data JPA doing any lazy initialization? Otherwise I'm out of explanations since it seems to be a persistent problem with the aspect not applied to the given bean for the lifetime of the application - that only makes sense when the race condition interferes during the initialization of a lazy-init singleton bean then. |
It could well be that this is a Spring Data problem. Would also explain why Boot 3.3.10 works with 6.2.5 Framework. When the first request hits, I just see this in the logs:
I'll try to get better logging. |
Those are the lazy beans in the context:
|
Hmm according to those request-initiated logs, the DispatcherServlet is not initialized on startup? It should usually be load-on-startup, shouldn't it? Tomcat should block the request(s) until the Servlet is initialized in any case but that increases the problem area. |
Yeah, that's the case for every Spring Boot application.
only appears when doing the 1st request. |
I disabled the lazy flag on the beans using this code: @Bean
static BeanFactoryPostProcessor beanFactoryPostProcessor() {
return (beanFactory) -> {
for(String beanDefName: beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanDefName);
if (beanDef.isLazyInit()) {
System.out.println("Disabling lazy on bean: " + beanDefName);
beanDef.setLazyInit(false);
}
}
};
} but the problem persists. |
Is there a specific reason why Boot initializes the DispatcherServlet lazily? In a good old In any case, it's worth testing with that DispatcherServlet Servlet registration marked as |
I don't know the reason why this isn't the default, but you can easily change that by setting a property:
we can now see that the servlet is initialized while starting up:
However, this doesn't fix that problem either. It's still occuring :/ // Edit: This issue is discussing dispatcherservlet load on startup. Seems like |
Ugh :-( Then I'm out of educated guesses, I'm afraid. So to summarize: An individual request warms it up properly but an initial load of 100000 requests breaks it, and it's not a temporary failure but rather the permanent absence of that aspect for the lifetime of the application. Something must trigger the lazy initialization of a repository bean without us realizing it, otherwise that permanent absence of the aspect is not explainable. In terms of further debugging: There must be a difference in application state before and after that initial warm-up request that makes the aspect applying to that repository bean. We need to track down what that difference is and how it is being created. |
Ah yes, good point. A concurrency level of 50 is pretty high in any case, and somehow able to trigger a race condition that otherwise remains unnoticed. The key question is how and when that aspect is being applied to that repository bean. There must be some laziness involved in the initialization there, otherwise it couldn't be exposed to that concurrency race condition and result in permanent application state. |
Potentially related to: |
In my Spring Boot 3.4.0 based application, I have an
@Aspect
namedTenantServiceAspect
that intercepts repository method calls to apply multi-tenancy filters using Hibernate filters.This aspect works perfectly fine in Spring Boot 3.3.10.
However, during load testing, sometimes when the application is restarted under heavy load, the
beforeExecution()
method of the aspect is not triggered for certain repository calls, especially this oneThe problem is not due to the load test. Since the load test constantly tries to make a request while the project is closed, when I restart the project, it probably causes this error because the request comes when the Spring Boot project is not fully ready.
Spring Boot version: 3.4.0
Java version: 21
Batch rest service
BatchBusinessService class
BatchRepository interface
Aspect class
Note: While investigating the root cause, I noticed something strange in Spring Boot's managed dependencies:
aspectjweaver
version 1.9.23aspectjweaver
version 1.9.22.13.3.10

3.4.0

While I haven’t confirmed the exact root cause yet, I’ve noticed that starting from Spring Boot 3.4.0, the spring-boot-starter-data-jpa no longer includes the spring-boot-starter-aop dependency by default:
Release Note:
“Remove spring-boot-starter-aop dependency from spring-boot-starter-data-jpa and spring-boot-starter-integration”
spring-projects/spring-boot#42934
I’m wondering if this change might somehow be related to the issue I'm facing — specifically, that sometimes my @aspect (TenantServiceAspect) does not get triggered in version 3.4.0, even though it works fine in 3.3.10.
It’s possible that under some conditions (e.g., app restarts, load), the absence of AOP support could lead to such inconsistent behavior.
Just sharing this in case it helps identify the root cause or helps someone else running into similar issues after upgrading to 3.4.0.
Intellij IDEA Profiler Fail and Successfull Output
The text was updated successfully, but these errors were encountered: