spring-attic / spring-native

Spring Native is now superseded by Spring Boot 3 official native support
https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html
Apache License 2.0
2.74k stars 356 forks source link

JacksonTester support leads to a circular reference with AOT #1464

Closed snicoll closed 1 year ago

snicoll commented 2 years ago

It looks like that the upgrade to the latest Spring Boot has brought a change in the testing support that triggers a cycle with AOT.

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  standardJacksonObjectMapperBuilderCustomizer
↑     ↓
|  jacksonTesterFactoryBean
↑     ↓
|  jacksonObjectMapper
↑     ↓
|  jacksonObjectMapperBuilder
└─────┘

stacktrace.

sdeleuze commented 2 years ago

I updated to 2.6.3-SNAPSHOT on Jan 13 (see this commit) and builds were green until Jan 19 included (see this build), that broke between Jan 19 and 21 I think.

What gives me hope that we are maybe not blocked is that the very same tests on JVM without AOT are fine, you can try with the new flag recently introduced mvn clean test -DspringAot=false. Could it be a side effect of #1458, #1459 or one of my changes?

sdeleuze commented 2 years ago

Bisected, introduced by 02d2f3a5fb79bed152ec7bf6b0914ff5839b14f5.

wilkinsona commented 2 years ago

I spent some time with Stephane looking at this and I think the changes in 02d2f3a have revealed an existing problem.

I think the cycle occurs because initializing the jacksonTesterFactoryBean requires the injection of the ApplicationContext into standardJacksonObjectMapperBuilderCustomizer. If this is the first time that the context has been injected via autowiring (rather than ApplicationContextAware) if triggers factory bean initialization at which point jacksonTesterFactoryBean is required again and a cycle is detected.

I believe it worked prior to the changes in 02d2f3a as creation of the configuration properties binder was triggering ApplicationContext injection and factory bean initialization earlier in the context's lifecycle via a portion of the graph that was not cyclic. This results in the "bean" for the ApplicationContext type being cached so that it was subsequently available for injection without triggering factory bean initialization.

If the above theory is correct, it would appear that without AOT something else is triggering eager ApplicationContext injection and FactoryBean initialization so the problem does not occur when JacksonTester is eventually being processed.

snicoll commented 2 years ago

To follow-up on this as this isn't the first time, the reason we have an eager init is because jacksonTesterFactoryBean is a FactoryBean with an unresolved generic. When that is the case, the context will eagerly initialize it whereas a runtime (non AOT) context will not. The difference is that AOT provides a supplier and the runtime does not so it parses the factory method signature.

snicoll commented 2 years ago

I have reverted the related problem and I've moved this change + an attempt to fix it in 462d217. This doesn't work yet.

sdeleuze commented 2 years ago

I am wondering if the point 3 of Matt Raible's comment here could be related:

If I'm using MVC + JPA, and I've added the Hibernate plugin, I have to turn off loading of SQL so Liquibase works:

spring:
 ...
 sql:
   init:
     mode: never

Without this change, the following error happens:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name >'dataSourceScriptDatabaseInitializer':
Circular depends-on relationship between 'dataSourceScriptDatabaseInitializer' and 'liquibase'
snicoll commented 2 years ago

No, that is a different problem. Anyway the current state of affair is so that the issue above doesn't occur as the change was reverted.

sdeleuze commented 1 year ago

Spring Native is now superseded by Spring Boot 3 official native support, see the related reference documentation for more details.

As a consequence, I am closing this issue, and recommend trying your use case with latest Spring Boot 3 version. If you still experience the issue reported here, please open an issue directly on the related Spring project (Spring Framework, Data, Security, Boot, Cloud, etc.) with a reproducer.

Thanks for your contribution on the experimental Spring Native project, we hope you will enjoy the official native support introduced by Spring Boot 3.