Shiv
Shiv

Reputation: 541

Spring Boot: Unable to read resources in lib/*.jar using a class in lib/*.jar

Iam using spring boot org.springframework.boot.loader.JarLauncher to run my self executable spring boot app jar.

Now, I have my self executable jar packed like this (For brevity Iam just adding the files only that are needed to show the problem):

Main.jar   
      ---META-INF
      ---lib
           ---a.jar
              ---com
                  ---comp
                     ---Abc.class
              ---folder1
                 ---1.txt
                 ---2.txt
           ---b.jar

and so on.

In my Abc.class Iam trying to load the resource 1.txt which is working fine when I run it in eclipse; but the story starts when I run using command line as self executable jar. I was not able to read that resource and ends up with null pointer error.

After reading few threads, I learnt that my IDEs does some magic on Class Loaders and so it was working fine, which will not be the case when I run it as executable jar

This is how I was Loading the files and the all the possible options I have tried to no luck.

Option 1:

Abc.class.getResourceAsStream("\folder1\1.txt")

Option 2:

Abc.class.getClassLoader().getResourceAsStream("folder1\1.txt")

Option 3: Reading thread, I have tried considered the current thread class loader context as below too, But to no luck again

Thread.currentThread().getContextClassLoader().getResourceAsStream("folder1\1.txt")

Can any one advise. How should I write my code to be able to read my resource that is in the jar and by the class that is in the same jar ?

PS: Spring boot is not adding class-path entry to MANIFEST.MF and if I have to do something around that, how do I do that ? In-fact I tried -cp when running my jar setting it to current directory, but that have not worked either

Upvotes: 1

Views: 7623

Answers (2)

Alexej Kubarev
Alexej Kubarev

Reputation: 853

In Spring, the best way to access a Resource is via Resource APIs. For a Classpath resource what you should use a ClassPathResource and it would look something like this:

Resource resource = new ClassPathResource("/my/resource.json", this.getClass());

After obtaining a Resource you can either get a File reference via getFile() or get an InputStream straight off by calling getInputStream().

Spring provides quite a few different implementations of the Resource interface, take a look at the list of known implementations in the docs

Upvotes: 3

luboskrnac
luboskrnac

Reputation: 24561

Use Spring's class ClassPathResource to load file from classpath.

For example you can read file into String like this from classpath:

String fileContent = FileUtils.readFileToString(
       new ClassPathResource("folder1" + File.separator + "1.txt").getFile());

It doesn't matter what kind of build tool or project structure you are using as long as that file is on classpath.

Upvotes: 1

Related Questions