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.
Comment From: pivotal-cla
@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.
Comment From: pivotal-cla
@vjh0107 Thank you for signing the Contributor License Agreement!
Comment From: wilkinsona
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.
Comment From: vjh0107
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
Comment From: philwebb
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.
Comment From: philwebb
We discussed this today and we think it's going to be safe enough to do in 3.1.x
Comment From: mhalbritter
Thank you very much and congratulations on your first contribution :tada:!
Comment From: izeye
This PR and its forward port issues have truncated titles.
Comment From: wilkinsona
Thanks, @izeye. I've updated the titles.
Comment From: mhalbritter
Mea culpa. Thanks!