Skip to content
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

Skip runtime hint registration for validation constraint with missing dependencies #33949

Closed
wants to merge 2 commits into from

Conversation

scordio
Copy link
Contributor

@scordio scordio commented Nov 23, 2024

Prior to this commit, AOT processing for bean validation failed with NoClassDefFoundError for constraints with missing dependencies. With this change, the processing no longer fails, and a warning is logged instead.

Example Log Message
16:16:31.245 [Test worker] WARN  o.s.v.b.BeanValidationBeanRegistrationAotProcessor - Skipping validation constraint hint inference for class org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests$ConstraintWithMissingDependency
java.lang.NoClassDefFoundError: org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests$Filtered
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests$FilteringClassLoader.loadClassForOverriding(BeanValidationBeanRegistrationAotProcessorTests.java:278) ~[test/:?]
	at org.springframework.core.OverridingClassLoader.loadClass(OverridingClassLoader.java:88) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
	at org.springframework.core.OverridingClassLoader.loadClass(OverridingClassLoader.java:82) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
	at java.base/java.lang.Class.getDeclaredFields0(Native Method) ~[?:?]
	at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3297) ~[?:?]
	at java.base/java.lang.Class.getDeclaredFields(Class.java:2371) ~[?:?]
	at org.hibernate.validator.internal.util.privilegedactions.GetDeclaredFields.run(GetDeclaredFields.java:30) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.util.privilegedactions.GetDeclaredFields.run(GetDeclaredFields.java:17) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.run(AnnotationMetaDataProvider.java:602) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getFieldMetaData(AnnotationMetaDataProvider.java:217) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.retrieveBeanConfiguration(AnnotationMetaDataProvider.java:130) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.getBeanConfiguration(AnnotationMetaDataProvider.java:121) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.getBeanConfigurationForHierarchy(BeanMetaDataManagerImpl.java:234) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.createBeanMetaData(BeanMetaDataManagerImpl.java:201) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl.getBeanMetaData(BeanMetaDataManagerImpl.java:165) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.getConstraintsForClass(ValidatorImpl.java:316) ~[hibernate-validator-7.0.5.Final.jar:7.0.5.Final]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessor$BeanValidationDelegate.processAheadOfTime(BeanValidationBeanRegistrationAotProcessor.java:125) ~[main/:?]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessor$BeanValidationDelegate.processAheadOfTime(BeanValidationBeanRegistrationAotProcessor.java:110) ~[main/:?]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessor.processAheadOfTime(BeanValidationBeanRegistrationAotProcessor.java:75) ~[main/:?]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests.createContribution(BeanValidationBeanRegistrationAotProcessorTests.java:144) ~[test/:?]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests.process(BeanValidationBeanRegistrationAotProcessorTests.java:134) ~[test/:?]
	at org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessorTests.shouldSkipConstraintWithMissingDependency(BeanValidationBeanRegistrationAotProcessorTests.java:129) ~[test/:?]

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 23, 2024
@scordio scordio force-pushed the gh-33940 branch 2 times, most recently from 04886d0 to 8753789 Compare November 23, 2024 15:56
@sbrannen sbrannen added type: regression A bug that is also a regression in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 23, 2024
@sbrannen sbrannen added this to the 6.2.1 milestone Nov 23, 2024
@sbrannen sbrannen self-assigned this Nov 23, 2024
@odrotbohm
Copy link
Member

I still think that we should avoid forwarding bean types of BeanDefinitions that don't use validation annotations by definition. Simply to avoid unnecessary work.

@scordio
Copy link
Contributor Author

scordio commented Nov 23, 2024

Thanks for the reminder, @odrotbohm! While working on this PR, I completely forgot about #33940 (comment), sorry about that.

I just pushed a possible solution for beans with ROLE_INFRASTRUCTURE. Do you think beans of type ROLE_SUPPORT are also relevant?

@sbrannen mentioned that he plans to discuss this change with the team next week.

@snicoll snicoll changed the title Skip AOT processing for validation constraint with missing dependencies Skip runtime hints harvesting for validation constraint with missing dependencies Nov 24, 2024
@snicoll
Copy link
Member

snicoll commented Nov 24, 2024

The role infrastructure looks a little bit arbitrary to me. I'd prefer if we use a signal that's more direct to the task at hand.

@scordio
Copy link
Contributor Author

scordio commented Nov 24, 2024

@snicoll for the scope of this PR, I propose I revert 5a50fcb and keep only 8753789 to address the issue reported at #33940, and I would leave the decision of further enhancements to the team.

WDYT?

@snicoll
Copy link
Member

snicoll commented Nov 24, 2024

Thanks for the suggestion. We can keep things as they are or drop the commit based on what the team decides.

@sbrannen sbrannen added type: bug A general bug type: regression A bug that is also a regression and removed type: regression A bug that is also a regression type: bug A general bug labels Nov 24, 2024
@edeandrea
Copy link
Contributor

Hi folks - do you know if there is any workaround for this issue? Currently it blocks an upgrade to SB 3.4.0. Removing the spring-boot-starter-validation dependency isn't an option.

@sbrannen
Copy link
Member

Hi folks - do you know if there is any workaround for this issue? Currently it blocks an upgrade to SB 3.4.0. Removing the spring-boot-starter-validation dependency isn't an option.

As an interim workaround (before 6.2.1 is released), you should hopefully be able to add the dependencies causing the problem.

For example, if you're seeing NoClassDefFoundError: org/reactivestreams/Publisher, adding a dependency on io.projectreactor:reactor-core may resolve the issue for you (again as a temporary workaround).

Please let us know if that works for you.

@sbrannen
Copy link
Member

Team Decision: Merge the PR without the BeanDefinition.ROLE_INFRASTRUCTURE check.

@sbrannen sbrannen changed the title Skip runtime hints harvesting for validation constraint with missing dependencies Skip runtime hint registration for validation constraint with missing dependencies Nov 27, 2024
sbrannen added a commit that referenced this pull request Nov 27, 2024
The log message for a NoClassDefFoundError is now a DEBUG level message
handled like a TypeNotPresentException and similar to the following.

DEBUG: Skipping validation constraint hint inference for class
org.example.CustomConstraint due to a NoClassDefFoundError for
com.example.MissingType

See gh-33949
@sbrannen sbrannen closed this in 9b0253e Nov 27, 2024
@sbrannen
Copy link
Member

This has been merged into 6.2.x and main in 9b0253e and revised in ea3bd7a.

Thanks, @scordio! 👍

@scordio scordio deleted the gh-33940 branch November 27, 2024 12:24
@scordio
Copy link
Contributor Author

scordio commented Nov 27, 2024

@edeandrea I can confirm that in an empty project with spring-boot-starter-data-jpa and spring-boot-starter-validation similar to what was reported at #33940, adding io.projectreactor:reactor-core (with runtime scope) allows processAot to succeed.

Just bringing the dependency might cause side effects with auto configurations like WebSessionIdResolverAutoConfiguration, depending on what else the application is doing, so my suggestion would be to evaluate the impact carefully (or just wait for the next Framework release).

edeandrea added a commit to edeandrea/quarkus-for-spring-devs-examples that referenced this pull request Nov 27, 2024
@edeandrea
Copy link
Contributor

Thank you @scordio - adding io.projectreactor:reactor-core with runtime scope fixed my issue for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: regression A bug that is also a regression
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AOT processing for bean validation fails with NoClassDefFoundError
6 participants