The JDK has decent support for walking a file system (via FileSystem in java.nio), but Spring still uses hand-rolled pre-Java 7 code. Also, in principle, FileSystem can be an abstraction used to express any hierarchy of resources through their URIs. This is a good fit with the Spring Resource abstraction, and for instance would mean that native images could potentially do classpath scanning through a custom URI and FileSystem already provided by GraalVM (https://github.com/oracle/graal/issues/1108).

Here's a prototype that shows how it could work: https://github.com/scratches/pattern-resolver-poc. It replaces one method (and several subsidiary protected methods) in PathMatchingResourcePatternResolver. The unit test is a copy from spring-core verifying that it works as normal with files. It also works with classpath resources in native images, as demonstrated by the main() method provided.

Slightly ugly is the hack that works around the fact that GraalVM's FileSystem for resource: URIs doesn't accept leading or trailing slashes in folder names (the opposite of the file: implementation provided by the JDK, but similar to the way ClassLoader.getResource() works).

Comment From: dsyer

Update: you can run the tests in the project above in a native image (./mvnw test -PnativeTest), but 1 of them had to be modified (there is no File associated with a classpath resource) and another disabled (you can't scan from the root of the classpath)

Comment From: bclozel

I've raised oracle/graal#5020 to address the lack of root resource resolution. I think this is a must have if we want to offer this feature in Framework. We don't need to wait for a fix in GraalVM though, as this issue would cover quite a lot of cases already.

Comment From: sbrannen

Related GraalVM Native Image Issues

  • https://github.com/oracle/graal/issues/5020
  • https://github.com/oracle/graal/issues/5080
  • https://github.com/oracle/graal/issues/5081

Comment From: sbrannen

Your work on this issue has been incorporated into the main branch in 0eb66789edd6122ab4f395b5a76d23255c0da337.

Thanks, @dsyer! 👏

Comment From: sbrannen

Update: you can run the tests in the project above in a native image (./mvnw test -PnativeTest),

To get PathMatchingResourcePatternResolverTests (current version from main) working, I ran the tests using the tracing agent (./mvnw clean -PnativeTest -Dagent=true test) and also had to create the following resource-config.json file.

{
    "resources": {
        "includes": [
            {
                "pattern": "^.+\\.dtd$"
            },
            {
                "pattern": "\\Qorg/springframework/core/io/\\E.*?\\/resource.+\\.txt$"
            },
            {
                "pattern": "\\Qorg/springframework/core/io/support/\\E.+\\.class$"
            },
            {
                "pattern": "\\Qreactor/util/annotation/NonNull.class\\E"
            },
            {
                "pattern": "\\Qreactor/util/annotation/NonNullApi.class\\E"
            },
            {
                "pattern": "\\Qreactor/util/annotation/Nullable.class\\E"
            }
        ]
    }
}

but 1 of them had to be modified (there is no File associated with a classpath resource)

I addressed that in 29442d4b7a92244399a4ce72e525d8ce71d405c0.

and another disabled (you can't scan from the root of the classpath)

Indeed, rootPatternRetrievalInJarFiles() is the only remaining test failing within a native image, but that will be addressed in https://github.com/oracle/graal/issues/5020.

Comment From: sbrannen

This has introduced a regression in that a matching folder is now returned in the results.

I am therefore reopening this issue to address that.