spring-boot icon indicating copy to clipboard operation
spring-boot copied to clipboard

startupTimeMetrics seems to cause bean dependency cycle when a MeterBinder uses a spring data repository

Open JakobFels opened this issue 3 years ago • 6 comments

Spring Boot version: 2.6.7

We seem to be running into an issue similar to https://github.com/spring-projects/spring-boot/issues/27591. We recently migrated one of our metric sources to use a spring data repository. This seems to cause a bean dependency cycle caused by startupTimeMetrics (See attached bean cycle screenshot). image

If needed, I can attempt to provide a minimal reproducer, but I hope the current information is enough.

JakobFels avatar May 09 '22 07:05 JakobFels

If needed, I can attempt to provide a minimal reproducer, but I hope the current information is enough.

Yes, please. I have been unable to reproduce the problem from what you have described thus far.

wilkinsona avatar May 09 '22 08:05 wilkinsona

While building the reproducer I noticed that the problem is caused by including spring-cloud-gcp-starter-data-firestore, with plain data-jpa I could not reproduce it as well.

I'll open an issue on that project.

JakobFels avatar May 09 '22 09:05 JakobFels

Thanks for letting me know. FWIW the dependency between serviceInstanceRepository and startupTimeMetrics looks a little unusual. If serviceInstanceRepository is a Data Firestore repository, that link is where I'd start looking.

wilkinsona avatar May 09 '22 09:05 wilkinsona

I opened a corresponding issue in the spring cloud gcp project: https://github.com/GoogleCloudPlatform/spring-cloud-gcp/issues/1113

JakobFels avatar May 09 '22 09:05 JakobFels

For posterity, the issue is not Firestore-specific, but adding metrics following Spring Boot docs avoids the cycle nicely.

In the reproducer, user implementation of MeterBinder inserted itself in the middle of Micrometer autoconfiguration. It also required a prerequisite service relying on a Spring Data repository, which had to get instantiated first. While instantiating the repository, org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport brings in org.springframework.data.repository.core.support.EventPublishingRepositoryProxyPostProcessor. Spring Data publishes org.springframework.data.mapping.context.MappingContextEvent when entity type is registered in RepositoryFactoryBeanSupport.afterPropertiesSet(). Because startupTimeMetrics is registered as an ApplicationListener, it has to get instantiated at that point, causing the cycle.

elefeint avatar Jun 24 '22 14:06 elefeint

For completeness; here is a reproducer without Firestore: https://github.com/elefeint/FirestoreMetricsReproducer/tree/h2-reproducer

elefeint avatar Aug 09 '22 14:08 elefeint