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

Metadata reading during configuration class parsing uses the default resource loader rather than the application's resource loader #39321

Closed
wants to merge 2 commits into from

Conversation

vjh0107
Copy link
Contributor

@vjh0107 vjh0107 commented Jan 27, 2024

I run Spring Boot in a complex resource loading environment, and no matter how I declare the resource loader and start the application, it always starts with the DefaultResourceLoader when class readings.

@pivotal-cla
Copy link

@vjh0107 Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 27, 2024
@pivotal-cla
Copy link

@vjh0107 Thank you for signing the Contributor License Agreement!

@wilkinsona
Copy link
Member

Thanks for the PR. There's a quite high risk of introducing a regression with a change like this so the bar has to be quite high for making a change. As such, I don't think that we can merge this without knowing more about your use case and why the current arrangement is insufficient. A minimal sample that shows things not working with the current code and that works with your proposed change in place would be very useful.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Feb 9, 2024
@vjh0107
Copy link
Contributor Author

vjh0107 commented Feb 10, 2024

Hello @wilkinsona,
In my project, each module resides in its own JAR file, and there are cases where modules reference classes from other JAR files.
When starting the application, Spring allows defining a ResourceLoader to specify where to get class files or resources. I fixed the issue where Spring Boot was not retrieving the ResourceLoader defined by the application. Instead of getting the defined ResourceLoader, Spring Boot only retrieves the ClassLoader of the defined ResourceLoader and reinstantiates the ResourceLoader as DefaultResourceLoader.

Here are the codes where BeanClassLoaderAware injects the ClassLoader from the ResourceLoader defined in the application:
https://github.com/spring-projects/spring-framework/blob/9333ed22f6ea6fae9909f6b6e6aa317c1b45ce82/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L1785

https://github.com/spring-projects/spring-framework/blob/0b96da4b6dfacf4b337f606cfa8fea117215fa53/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L715

https://github.com/spring-projects/spring-framework/blob/aaeb5eb0d211ebd1946bc61ee062ec7102f49d91/spring-core/src/main/java/org/springframework/core/io/DefaultResourceLoader.java#L97

This is the stack trace of the exception:

Caused by: java.io.FileNotFoundException: class path resource [org/example/ExampleFromExternalJar.class] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:211) ~[spring-core-6.0.13.jar:6.0.13]
	at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:54) ~[spring-core-6.0.13.jar:6.0.13]
	at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:48) ~[spring-core-6.0.13.jar:6.0.13]
	at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-6.0.13.jar:6.0.13]
	at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86) ~[spring-boot-3.1.5.jar:3.1.5]
	at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73) ~[spring-boot-3.1.5.jar:3.1.5]
	at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81) ~[spring-core-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:613) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getSuperClass(ConfigurationClassParser.java:926) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:334) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:243) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:188) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:297) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:243) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:196) ~[spring-context-6.0.13.jar:6.0.13]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:164) ~[spring-context-6.0.13.jar:6.0.13]
	... 24 more

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 10, 2024
@philwebb
Copy link
Member

I think this is a sensible change to make. Looking at this code, it seems like our fallback code uses the resource loader where as SharedMetadataReaderFactoryBean uses the classloader.

Flagging for team attention to see if we think it's too risky for a patch release change.

@philwebb philwebb added for: team-attention An issue we'd like other members of the team to review type: bug A general bug and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Feb 12, 2024
@philwebb philwebb added this to the 3.1.x milestone Feb 15, 2024
@philwebb
Copy link
Member

We discussed this today and we think it's going to be safe enough to do in 3.1.x

@vjh0107 vjh0107 changed the base branch from main to 3.1.x February 16, 2024 05:23
# Conflicts:
#	gradle.properties
#	spring-boot-project/spring-boot-dependencies/build.gradle
#	spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java
#	spring-boot-project/spring-boot-tools/spring-boot-loader-classic/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java
#	spring-boot-project/spring-boot-tools/spring-boot-loader-classic/src/main/java/org/springframework/boot/loader/archive/JarFileArchive.java
#	spring-boot-project/spring-boot-tools/spring-boot-loader-classic/src/main/java/org/springframework/boot/loader/jar/Handler.java
#	spring-boot-project/spring-boot-tools/spring-boot-loader-classic/src/main/java/org/springframework/boot/loader/jar/JarFile.java
@mhalbritter
Copy link
Contributor

Thank you very much and congratulations on your first contribution 🎉!

@mhalbritter mhalbritter modified the milestones: 3.1.x, 3.1.9 Feb 16, 2024
@izeye
Copy link
Contributor

izeye commented Feb 21, 2024

This PR and its forward port issues have truncated titles.

@wilkinsona wilkinsona changed the title Change ConcurrentReferenceCachingMetadataReaderFactory to use applica… Metadata reading during configuration class parsing uses the default resource loader rather than the application's resource loader Feb 21, 2024
@wilkinsona
Copy link
Member

Thanks, @izeye. I've updated the titles.

@mhalbritter
Copy link
Contributor

Mea culpa. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants