1 year ago

#70897

test-img

tortoiseparrot

How to ensure Spring `Resource::createRelative` returns relative file resource for directory resource without trailing slash?

Hej,

in a Spring Boot application I need to use a base directory on the filesystem and access file resources relative to that. Spring Boot allows to configure a directory via application.properties and a file:// URL as value. When the property is missing its trailing slash, Resource::createRelative() fails to actually return a relative resource.

What kind of code or configuration do I need to make the createRelative() call work as intended, e.g. by ensuring that the Resource ends with a trailing slash?

The follwing test should illustrate my use case / problem:

@SpringBootTest
// NOTE: directory is missing trailing slash
@TestPropertySource(properties = "demo.directory=file://C:/Windows")
class RelativeFileUrlResourceTest {

    @ConfigurationProperties(prefix = "demo")
    static class TestProperties {

        Resource directory;

        public Resource getDirectory() {
            return directory;
        }

        public void setDirectory(Resource directory) {
            this.directory = directory;
        }
    }

    @TestConfiguration
    @EnableConfigurationProperties(TestProperties.class)
    static class Config {

    }

    @Autowired
    TestProperties testProperties;

    @Test
    void givenCreateRelative_thenResourceShouldBeRelative() throws IOException {
        Resource directoryResource = testProperties.getDirectory();
        File directoryFile = directoryResource.getFile();
        assertTrue(directoryFile.isDirectory());

        Resource relativeResource = directoryResource.createRelative("relative");
        File relativeFile = relativeResource.getFile();
        assertEquals(directoryFile, relativeFile.getParentFile());
    }
}

The test fails with:

org.opentest4j.AssertionFailedError: 
Expected :C:\Windows
Actual   :C:\

The magic C:/Windows value is just an example of a folder that exists and does not have a trailing slash for test purposes. Once the trailing slash is added, i.e. C:/Windows/, the test passes.

Further note that both the canonical and absolute directory File do not contain a trailing slash either (at least tested on Windows). The relative (file) resource is needed to pass it up all the way to a Spring MVC controller while using the Spring Resource abstraction to access it as a generic InputStream. The actual application contains some logic to determine the relative file from the HTTP request instead of a hardcoded "relative" filename.

Is Resource::createRelative() unfit for this kind of use case? What other abstractions / solutions does Spring (Boot) offer?

java

spring

spring-boot

directory

filepath

0 Answers

Your Answer

Accepted video resources