Version: Spring Boot 2.3.x
Minimal example: Autowiring for instance an objectMapper into a custom AttributeConverter works fine with all versions of spring-boot v2.2.x. However, when upgrading to spring-boot 2.3.0 the objectMapper is no longer autowired and the application freezes indefinitely and doesn't start up.
Example of AttributeConverter:
@Component
public class StringListToJsonConverter implements AttributeConverter<List<String>, String> {
private static ObjectMapper objectMapper;
@Autowired
public void init(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public String convertToDatabaseColumn(List<String> documentObj) {
// Do some logic...
}
@Override
public List<String> convertToEntityAttribute(String documentStr) {
// Do some logic...
}
}
Comment From: snicoll
Thanks for the report. It is likely to be due to JPA deferred mode. Can you please try with the latest release for a start, i.e. 2.3.5.RELEASE
? If that's still broken, please share a minimal example we can actually run (rather that code in text). You can do so by attaching a zip to this issue or share a link to a GitHub repository.
Comment From: Miicroo
@snicoll Tried using default
as BootstrapMode, and now all beans are autowired correctly. Thank you for the help, I am closing this since their was no real issue :)
Comment From: snicoll
Thanks for letting us know but that's working around the issue. We'd like to understand if we could do something so that your use case works out-of-the-box. Can you please test your application unchanged (without the default
bootstrap mode) with Spring Boot 2.3.5.RELEASE
? If that still breaks, could you help us by sharing a small sample?
Comment From: steklopod
Have similar issue when using gradle plugin and @AutoConfigureMockMvc
id("org.springframework.boot") version "2.3.5.RELEASE"
All @IntegrationTest
ok, but when first @WebTest
test freeze and never ends.
But with 2.3.4.RELEASE
- no such problem
// OK
@SpringBootTest
@Target(CLASS)
@Retention(RUNTIME)
@ActiveProfiles("test")
annotation class IntegrationTest
// Freeze (deadlock)
@Target(CLASS)
@Retention(RUNTIME)
@IntegrationTest
@AutoConfigureMockMvc
annotation class WebTest
Also in this project I'm using liquibase
. No exception. Just deadlock
@WebTest
internal class UserControllerTest(@Autowired private val mockMvc: MockMvc) {
private val baseUrl = "/user"
@Test
fun userTest() {
mockMvc.perform(postWithTokenInHeader(baseUrl))
// .andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk)
}
Comment From: wilkinsona
Thanks, @steklopod. Could you please open a new issue with a minimal sample that reproduces the problem?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: Miicroo
@snicoll Sorry for the long delay, I have uploaded the following example (with data.jpa.repositories.bootstrap-mode: default
commented out and spring-boot 2.3.5). Without bootstrap-mode: default it still hangs for med om java 11.
test-autowire-objectmapper.zip
Comment From: snicoll
Thank you very much for taking the time to share a sample @Miicroo. I've reproduced the deadlock and will look at the code in more details to see if there's a workaround or something we can change ourselves to avoid the problem.
Comment From: snicoll
So there's a number of things going on there. With deferred JPA bootstrap, you're not supposed to use the JPA infrastructure on startup but Api
injects a Repository
and then use it to save an object. I've moved this piece of code to a later phase using SmartInitializingSingleton
and the deadlock went away.
The StringListToColumnConverter
is another area of improvement. Rather than injecting the ObjectMapper
upfront (which triggers a bean resolution that can lead to a lock) you could inject an ObjectProvider<ObjectMapper>
and resolve the actual bean on first use only. This also removes the deadlock.
We've got a number of reports similar to yours in the recent past so I think we need to do something in our documentation to warn users what deferred JPA bootstrap entails. Let's reuse this issue for that.
Comment From: Miicroo
Thanks for the explanations, really nice to hear about how it should be done. I wrote the example just as a quick-throw-together-app, a more realistic example would be that the Api
uses som service
which under the hood uses a repository
. Would that lead to the same problem? My guess is yes, since the only difference would be the number of beans that need to be resolved compared to the example app.
Comment From: snicoll
Thanks for the feedback.
Would that lead to the same problem? My guess is yes, since the only difference would be the number of beans that need to be resolved compared to the example app.
Yes, it doesn't matter how much hop. Using the JPA infrastructure as part of the BeanFactory
bootstrap is the problem.