echo $my_thoughts > /dev/null

Code, philosophy and scribblings

Spring Boot - How to Serve Static Files Without Reloading the Application

The default way of serving static files like JS & CSS via Spring Boot is to put your static folder under /src/main/resources/public. The Internet will give you all kinds of variations of this solution, but almost all of the solutions have a problem.

The static files will be bundled up into the JAR file (that is if you are using the embedded server that comes with Spring). This means you have to reboot the JAR / application everytime you change your CSS or JS. Things could get really painful when you already have a webpack compile process, that will be chained to a JAR compile process.
If you use IntelliJ, there’s a solution to auto-reload your app everytime static files change. This one has its own problems. If you don’t edit static files from your IntelliJ and instead use WebStorm / Sublime / VSCode you need to come back to the IntelliJ window once after editing, so that IntelliJ knows that it should reload static. Fail.

So here’s a solution that worked for me: simply put static resources out of the JAR and write a URL handler that serves static resources from the filesystem. This can be done by hijacking Spring’s default /static url handler and writing your own.

Put your static file in the root folder alongside /src.

1
2
3
4
5
6
7
8
9
myapplication/
           /bin
           /libs
           /src
           /static  ---------> your static folder
                  /css
                      /main.css
                  /js
                      /main.js

Include the following URL handler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * THIS ENDPOINT IS JUST FOR DEV.
 * PRODUCTION MODE SHOULD ALWAYS SERVE STATIC FILES FROM A SEPARATE SERVER
 *
 */
@GetMapping(value = "static/**")
public void serveStatic(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

    /*
     * if /static/css/main.css lands here -> path = "/static/css/main.css"
     */
    String path = request.getRequestURI();

    /*
     * with IntelliJ cwd will by default point to "/home/.../application"
     */
    String cwd = Paths.get(".").toAbsolutePath().normalize().toString();
    File file = new File(cwd + path);

    /*
     * If you want you can have your static folder anywhere on your filesystem. Just make sure file object points to the correct path.
     */
    FileInputStream inStream = new FileInputStream(file);
    OutputStream outStream = response.getOutputStream();
    String mimetype = Files.probeContentType(file.toPath());
    response.setContentType(mimetype);

    byte[] buffer = new byte[4096];
    int bytesRead = -1;

    while ((bytesRead = inStream.read(buffer)) != -1) {
        outStream.write(buffer, 0, bytesRead);
    }

    inStream.close();
    outStream.close();
}

With this in place, your spring boot application doesn’t have to be reloaded everytime you change the font-color. Happy Coding!