Search code examples
javaspringclasspathclassloader

Spring 5.1.2 PathMatchingResourcePatternResolver detects files on root of jar


I was reading spring docs regarding classpath* and I found :

Please 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 ClassLoader.getResources() method which only returns file system locations for a passed-in empty string (indicating potential roots to search).

when I was trying this locally I was confused that it worked on root of jars , example :

test.txt resource exists in test2 root ( which is the class I run the application from ) , and there is also test.txt on test which is dependency on test2

Project test2 :

    @RunWith(JUnit4.class)
public class TestDriver {
@Test
public void test() throws IOException {

    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    System.out.println(Arrays.toString(resolver.getResources("classpath*:*test.txt")));
    Enumeration<URL> enumeration= this.getClass().getClassLoader().getResources("");
    int count=0;
    while(enumeration.hasMoreElements()){
       URL url= enumeration.nextElement();
       System.out.println(url.getFile());
        count++;
    }
    System.out.println(count);
}

}

output :

[URL [jar:file:/C:/.../.m2/repository/com/test/1.0-SNAPSHOT/test-1.0-SNAPSHOT.jar!/test.txt]] --- > The question how this text file detected while it's on the root of a jar , according to docs it shouldn't be detected

from "this.getClass().getClassLoader().getResources("")" there is only 2 roots ( test jar is not part of them ) :

/..../test2/target/test-classes/

/..../test2/target/classes/

2


Solution

  • The doc refers to the reliability of the resource lookup in this specific case.
    You can also read at the end of this warning part of the PathMatchingResourcePatternResolver javadoc (emphasis is mine) :

    WARNING: Note that "classpath*:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts

    ...

    This ResourcePatternResolver implementation is trying to mitigate the jar root lookup limitation through URLClassLoader introspection and "java.class.path" manifest evaluation; however, without portability guarantees.

    It seems that it works for your case.