Resolving Spring Boot Resource Loading Errors When Running from a JAR
This article explains why a Spring Boot application fails to locate a template file when packaged as a JAR, details the step‑by‑step debugging process, and provides code solutions using ClassPathResource or PathMatchingResourcePatternResolver to correctly read resources inside the JAR.
When reading files from the resources directory, the code works locally but throws an error in the test environment: class path resource [xxxx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxxx.jar!/BOOT-INF/classes!xxxx .
1. Project Code
GetResourceTest :
public class GetResourceTest {
public InputStream getResource1() throws IOException {
File file = new DefaultResourceLoader().getResource("/template/qiankuan.ftl").getFile();
return Files.newInputStream(file.toPath());
}
public InputStream getResource2() throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
return resource.getInputStream();
}
}TestController :
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping(value = "/getResource")
@ResponseBody
public void getResource() throws IOException {
GetResourceTest getResourceTest = new GetResourceTest();
getResourceTest.getResource1();
}
}2. Investigation Process
1) Build the project into a JAR with Maven
The mvn install command creates the JAR in the target directory.
2) Run the JAR with remote debugging
java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9992 api-test-1.0.0-SNAPSHOT.jarThe application starts successfully.
3) Add remote debugging configuration
In the IDE, add a Remote JVM Debug configuration and set the port to the one used above (e.g., 9992).
4) Call the test endpoint
Request: http://127.0.0.1:9991/test/getResource
5) Observe the error
The response shows the same FileNotFoundException as in the test environment.
6) Debug with breakpoints
Setting a breakpoint at the controller entry reveals that the resource path is resolved to a JAR URL like jar:file:/.../api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/template/qiankuan.ftl , and resourceUrl.getProtocol() returns jar instead of file , causing the exception.
3. Solution
The ResourceUtils.getFile() method only works for non‑compressed files and cannot read resources inside a JAR. Use a method that reads the resource as a stream, such as ClassPathResource or PathMatchingResourcePatternResolver :
ClassPathResource classPathResource = new ClassPathResource("/template/qiankuan.ftl");
InputStream inputStream = classPathResource.getInputStream();or
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
InputStream inputStream = resource.getInputStream();These approaches correctly load the template file whether the application runs from the IDE or from a packaged JAR.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.