0

I'm using spring boot and storing my static content (html, css, etc.) as src/main/webapp. I understand that this is not recommended, because it won't be stored in jar file (should be in /META-INF/resources/, /resources/, /static/, /public/). But my question is not about storing static content in jar.

This is project structure:

App
 ├──src
 |   └───main
 |        ├── java
 |        |     └── ...
 |        ├── resources
 |        |     └── (everything here will be in jar)
 |        └── webapp <- this won't be in jar
 |               └── ...
 └ target
     └───App.jar

When I'm trying to run jar from App folder as java -jar target/App.jar, spring boot finds static content and works fine. However running it from target folder as java -jar App.jar won't find static content.

How to run App.jar from target folder and let spring boot find static content? Is it related to the classpath? I was trying to specify the classpath with -cp option, but it doesn't work.

Dmitry K
  • 1,142
  • 2
  • 16
  • 27

2 Answers2

1

There's a point of view that this is a build problem. I don't mean a packaging problem (I know you don't want to put it into the jar). But you have another option: your build system (e.g. Maven) can copy static files into the target folder.

This answer demonstrates the use of maven-antrun-plugin to invoke Ant's copy command. This will put a copy of your static file into the target folder.

Obviously change the execution phase (test phase is too specific/late for your use-case). And maybe lookup whether there's a more Maveny way to do it (since delegating to Ant is not super-idiomatic).

Birchlabs
  • 7,437
  • 5
  • 35
  • 54
  • This plugin is copying single file. I found `maven-resources-plugin` and it can copy multiple resource directories to independent directories, but I don't think it is a good solution. I was thinking about something like changing working directory as you suggested, but think it's a dead-end. – Dmitry K Sep 06 '17 at 12:25
  • out of curiosity: why don't you think build is a good way to solve this? `target` is the output of your project. everything you want to _ship_ or _run_ should get output into that folder. do you dislike having copies of the files? do you dislike having to keep them up-to-date? build should be invoked whenever source changes, so it's easy to keep things up-to-date. otherwise: the ant copy task can create symbolic links (though I don't recommend it). – Birchlabs Sep 06 '17 at 12:36
  • Well, I agree with you. It's not that bad :) I was able to succeed by manually copying `webapp` folder to `target/src/main`. So I guess your option with maven plugin will work fine too. I am wondering is it the only way? I found `spring.resources.static-locations` property but not sure what should be there. – Dmitry K Sep 06 '17 at 13:17
  • hm, I don't think `spring.resources.static-locations` can be used to specify an absolute path. its default value is `/**`, but that seems to refer to the root of the classpath or perhaps to the root of `usr.dir`. I don't think you can navigate upward from there. – Birchlabs Sep 06 '17 at 13:32
  • I think copy static files into the target folder is simplest solution. Thank you – Dmitry K Sep 06 '17 at 14:47
0

It's searching relative to the working directory of the executable at runtime. Since it's using a relative path to lookup the file (e.g. src/main/webapp/file.txt), your working directory needs to be /path/to/App.

You can change the working directory using -Duser.dir.

I recommend trying this:

java -Duser.dir=../ -jar App.jar

Or maybe it needs to be an absolute path. Tell me whether it works; I've not got the project to try it out.

Birchlabs
  • 7,437
  • 5
  • 35
  • 54
  • It does not work: "Error: Could not find or load main class .dir=../". I also tried `-Duser.dir=D:/App.` – Dmitry K Sep 06 '17 at 11:17
  • Ah, it's Windows; maybe you need backslashes? ..\ or D:\App. Depending on the shell you're using, you may need to escape these backslashes: ..\\ or D:\\App – Birchlabs Sep 06 '17 at 11:22
  • if there's any ambiguity as to _where_ Spring Boot is searching, you can use [ProcMon](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) to snoop all file accesses on Windows. You can look for failed file lookups attempted by java, and this should tell you the absolute path to which it resolved your relative path. This will give an indication of whether `-Duser.dir` is having _any_ effect (and just needs a bit of tweaking), or if it's a dead-end. – Birchlabs Sep 06 '17 at 11:30
  • I think `-Duser.dir` is having effect, because now I having this Error: Could not find or load main class org.springframework.boot.loader.JarLauncher. – Dmitry K Sep 06 '17 at 11:38
  • @Birchlabs I think you need to merge these two answers, :) – bananas Sep 06 '17 at 11:43
  • @I_Am_Innocent why? they're different answers; they are two threads of discussion, either could be individually wrong or right, and either could be accepted as the preferred answer. – Birchlabs Sep 06 '17 at 11:56
  • the other way to solve this is with an application-layer fix. `src/main/webapp/file.txt` is a relative path, so you need to either regain control of how it's resolved to an absolute path (there may even be a Spring Boot-specific way to do this), or you need to start referring to it using an absolute path. You could make this configurable, if you need it to be environment-agnostic. – Birchlabs Sep 06 '17 at 12:41