I'm running a Spring Boot application in Heroku, using Maven to manage the build lifecycle.
During the initialisation phase of my application, I want to read a file packaged into my JAR file.
To manage to get the content of the file I'm using the Spring utility class ResourceUtils
, and I'm expressing the path of the file using the special prefix classpath:
.
The code I'm using looks like this:
String pathToMyFile = "classpath:com/myapp/myFile.test"
List<String> fileLines = Files.readLines(ResourceUtils.getFile(pathToMyFile), IOConstants.DEFAULT_CHARSET_TYPE);
This code works as expected when I execute the application in my local machine.
But when I push my application to Heroku I'm getting the following error:
Caused by: java.io.FileNotFoundException: class path resource [com/myapp/myFile.test]
cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/app/target/myapp.jar!/com/myapp/myFile.test
I've run a heroku run bash
and I've checked that the file is just where it should be (inside the jar).
Moreover, according to the error trace, Spring locates the file, because it transform the path from classpath:com/myapp/myFile.test
to jar:file:/app/target/myapp.jar!/com/myapp/myFile.test
It's a path inside your project where you place resources. During the build step, Maven will take files in there and place them in the appropriate place for you to use them in your runtime classpath, eg in an executable . jar , some physical file system location used in the classpath (with java 's -cp option), etc.
Spring Boot Resource Resource is data, such as images, audio, and text, that a program needs to access in a way that is independent of the location of the program code. Because java. net. URL is not adequate for handling all kinds of low level resources, Spring introduced org.
I suspect that when you are running locally, it is picking up the file on the classpath from an exploded JAR file (i.e. as a regular file on the filesystem).
On Heroku, it is in the JAR file, which means it is not a regular file, and must be read as an input stream, which might look like this:
ClassLoader cl = this.getClass().getClassLoader();
InputStream inputStream = cl.getResourceAsStream(pathToMyFile);
Then you might use a BufferedReader to read the lines. But maybe ResourceUtils
has a better method.
You can probably reproduce the problem locally by running the same command that's in your Profile
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With