Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ResourceUtils.getFile to read a file from classpath in Heroku environment

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

like image 566
jfcorugedo Avatar asked Mar 01 '16 15:03

jfcorugedo


People also ask

What is classpath in spring boot application?

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.

What is @resource in spring boot?

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.


1 Answers

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.

like image 155
codefinger Avatar answered Oct 03 '22 10:10

codefinger