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

Change in BeanFactoryUtils.beanNamesForTypeIncludingAncestors() Behavior in Spring Framework 6.2.x causing ClassCastExceptions #34300

Open
rj-cam opened this issue Jan 21, 2025 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression
Milestone

Comments

@rj-cam
Copy link

rj-cam commented Jan 21, 2025

There is an unexpected change in behavior in how BeanFactoryUtils.beanNamesForTypeIncludingAncestors() as well as ListableBeanFactory.getBeanNamesForType(ResolvableType) handles generic types in the new Spring Framework 6.2.x compared to 6.1 and even in 5.x.

HOW TO REPRODUCE
I was able to reproduce the issue and verify it in the older versions. Just clone the repository, change the Spring Boot version accordingly, build and run the one and only JUnit test: https://github.com/rj-cam/beans-for-type/tree/main

Please refer to the README.MD for a summary of the code.

IMPACT
Unfortunately, due to additional beans being included that are superclasses of the expected generic type, we are now facing a slew of unexpected java.lang.ClassCastException.

For example:

java.lang.ClassCastException: class com.x.security.core.biz.domain.prelogin.PreloginInitRequest cannot be cast to class com.x.commons.core.biz.domain.TwoFAuthBizRequest (com.x.security.core.biz.domain.prelogin.PreloginInitRequest and com.x.commons.core.biz.domain.TwoFAuthBizRequest are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4663f2d1)

Please advise if this is the expected behavior in Spring Framework from now on and if there is a way to access the old functionality. Or if not, hopefully, it's a simple fix.

Sadly, this is a showstopper for our upgrade to the latest Spring Framework version. I'm thinking of a workaround to double-check the generic type and ensure it is a sub-class of the expected type (CharlieRequest in Processor<CharlieRequest>) but I am stuck trying to get the actual type. Using ResolvableType.forInstance(bean).getGeneric(0) on the errant CharlieSubGenericProcessor<REQ extends CharlieSubRequest> bean returned by BeanFactoryUtils is returning ? for its generics type.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 21, 2025
@jhoeller
Copy link
Contributor

Have you tried running this against the just-released Spring Framework 6.2.2 release (to be included in this week's Spring Boot 3.4.2)? Several generic type matching regressions have been addressed there: see #34119 and #34234.

@rj-cam
Copy link
Author

rj-cam commented Jan 22, 2025

Looked into the issues, it seems related but unfortunately, the tests are still failing even with:

ext['spring-framework.version'] = '6.2.2'

Validated the classpath to be sure.

testRuntimeClasspath - Runtime classpath of source set 'test'.
+--- org.springframework.boot:spring-boot-starter -> 3.4.1
|    +--- org.springframework.boot:spring-boot:3.4.1
|    |    +--- org.springframework:spring-core:6.2.1 -> 6.2.2
|    |    |    \--- org.springframework:spring-jcl:6.2.2
|    |    \--- org.springframework:spring-context:6.2.1 -> 6.2.2
|    |         +--- org.springframework:spring-aop:6.2.2
|    |         |    +--- org.springframework:spring-beans:6.2.2
|    |         |    |    \--- org.springframework:spring-core:6.2.2 (*)
|    |         |    \--- org.springframework:spring-core:6.2.2 (*)
|    |         +--- org.springframework:spring-beans:6.2.2 (*)
|    |         +--- org.springframework:spring-core:6.2.2 (*)
|    |         +--- org.springframework:spring-expression:6.2.2
|    |         |    \--- org.springframework:spring-core:6.2.2 (*)
|    |         \--- io.micrometer:micrometer-observation:1.14.3 -> 1.14.2
|    |              \--- io.micrometer:micrometer-commons:1.14.2

#33982 and #34234 are interesting because now I need to check Processor<A, B> next. The behavior there might have changed as well.

@rj-cam
Copy link
Author

rj-cam commented Jan 22, 2025

Updated the GitHub Project

  • Simulate the java.lang.ClassCastException we are facing due to the unexpected bean matching
  • Added a new test class BeansfortypeApplicationTests2 for validating two generics scenario we are also using and confirmed it is also failing in 6.2.x and working fine in 6.1.x
  • Updated Spring Framework version to 6.2.2 as advised

Image
Image

@jhoeller jhoeller self-assigned this Jan 22, 2025
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 22, 2025
@jhoeller jhoeller added this to the 6.2.3 milestone Jan 22, 2025
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) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

3 participants