Affects: spring-core
5.3.18
When looking up a resource that's contained in the root of a dependency jar with a path wildcard, PathMatchingResourcePatternResolver
gives different results depending on the way the classpath is given to java
.
Taking the JUnit 4 JAR as a readily available example, from what I would expect from the docs,
new PathMatchingResourcePatternResolver().getResources("classpath*:**/LICENSE-junit.txt")
and
getClass().getClassLoader().getResources("LICENSE-junit.txt")
should find the same resource. However, if the java
process is called with the classpath given in a JAR file containing the dependency JAR in its manifest, PathMatchingResourcePatternResolver
does not find the resource.
See https://github.com/cnaj/path-matching-resource-pattern-resolver-demo for a demo of this behavior.
Please run the two scripts demo-normal-cp.sh
and demo-jar-cp.sh
in the demo repository to see the difference in behavior.
Tested with Java 8 and Java 11 on Windows, Linux, and Mac.
This behavior has already been reported previously with #24480, but it was apparently mistaken for a VS Code behavior.
Comment From: Flaurite
I faced the same problem with PathMatchingResourcePatternResolver
that it does not check resources from MANIFEST.MF
"Class-Path" attribute.
If the class path is very long, Gradle creates a temporary jar file that contains all "Class-Path" for the application (on Windows OS).
When PathMatchingResourcePatternResolver#addClassPathManifestEntries()
method is invoked it tries to get resources from "java.class.path" system property, however in this case, it contains only one temporary jar. And it does not collect resources
from this jar.
I've prepared demo project with Spring Boot 3.0.5 that uses Spring Core 6.0.7. Note, to increase Class-Path I've added some dependencies from this file: https://github.com/jmix-framework/jmix/blob/master/jmix-bom/bom.gradle
Demo: spring-long-class-path.zip
Application tries to find com.google.common.base.Strings
class. In logs it shows "true" or "false" depending on "Class-Path" length.
Comment From: snicoll
@cnaj thanks very much for the sample, that's very useful. I can reproduce with the current GA of the framework so we'll have to investigate what's going on.
Comment From: snicoll
PathMatchingResourcePatternResolver
has this note:
WARNING: Note that "classpath*:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "classpath*:*.xml" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's
Unfortunately, there's nothing we can do about that.