27

I'm trying to run Spring boot app with some HTML5 and JavaScript and I have a problem.

I have project structure like this:

enter image description here

My Spring MVC Controller is calling file offer.html and that works ok.

My offer.html file look like this:

<!DOCTYPE html>
<html lang="en" ng-app="coByTu">
<head>
    <title>Page</title>
    <script type="text/javascript" src="../js/lib/angular.js" />
    <script type="text/javascript" src="../js/src/offer.js" />
</head>
<body>

</body>
</html>

And when I'm typing my app URL http://localhost:8080/offerView

response from server is:

enter image description here

I have no idea why my app doesn't see this script files, could any one have any idea what i did wrong?

1

7 Answers 7

65

Basically all content that needs to be served staticly (such as javascript files) should be placed under the static folder. https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

I've thrown together a quick working example to show how it is done: https://github.com/ericbv/staticContentWithSpringBoot

File structure: enter image description here

HTML file:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Page</title>
    <script type="text/javascript" th:src="@{/js/lib/angular.js}" />
    <script type="text/javascript" th:src="@{/js/src/offer.js}" />
</head>
<body>

Using th:src will make sure that the links are context aware

Edit: added the th:src to make the references context aware

Sign up to request clarification or add additional context in comments.

6 Comments

I sugest to not use thymeleaf here :) <script type="text/javascript" src="/js/lib/angular.js" /> <script type="text/javascript" src="/js/src/offer.js" /> is good enought.
Ass I assume when Spring Boot creates Resource Handlers for files contained in /static directory, and I want reffer to this Resource Handler in my offer.html using tag <script src... my Container is forced to apend this Resource Handlers path to application context ( context in this case localhost:8080 ) and under the hood it creates something like localhost:8080/js/src/offer.js?
Thats a bad practice. Not using thymeleaf here will break the page when there is a contextPath (i.e. when used inside of a standalone application server)
It wont work if your app has a contextpath. In general you will have a context path when running your app from a standalone application server or because its added in application.properties. If you want to simulate a context path (to see when using just src breaks) add the folowing line to your applicaiton.properties file: "server.contextPath=/context" This will cause the page url to be localhost:8080/context/offerView Now in this case it will only work with the thymeleaf variant of src because this will take the context into account.
So app stack is Angular + Thymaleaf + Spring Boot, but as I want build single page application I don't understand Thymeleaf role as template engine here.
|
7

just for anyone to find this page with the same issue. The way I resolved the 'script is not executed' problem was pretty simple.

Simply replaced :

<script type="text/javascript" src="js/src/Test.js" />

with

<script type="text/javascript" src="js/src/Test.js" ></script>

(Test is located in 'static/js/src') Hopefully this is helpful to anyone but me :)

cheers

Comments

3

You need to put your static js files into static folder. See more here: https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

1 Comment

Sorry but this link is not helping.
1

I think you need to move the js directory (and contents) into the static directory (rather than having it in templates).

1 Comment

I have tried this before but i didn't resolve my problem.
1

I added spring.mvc.static-path-pattern=/static/** to application.properties file and now it works.

In html I use like this src="/static/js/jQuery.min.js"

Comments

0

Set the document root directory which will be used by the web context to serve static files using ConfigurableEmbeddedServletContainer.setDocumentRoot(File documentRoot).

Working example:

package com.example.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.File;
import java.nio.file.Paths;

@Configuration
public class WebConfigurer implements ServletContextInitializer, EmbeddedServletContainerCustomizer {
    private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);

    private final Environment env;
    private static final String STATIC_ASSETS_FOLDER_PARAM = "static-assets-folder";
    private final String staticAssetsFolderPath;

    public WebConfigurer(Environment env, @Value("${" + STATIC_ASSETS_FOLDER_PARAM + ":}") String staticAssetsFolderPath) {
        this.env = env;
        this.staticAssetsFolderPath = staticAssetsFolderPath;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        if (env.getActiveProfiles().length > 0) {
            log.info("Web application configuration, profiles: {}", (Object[]) env.getActiveProfiles());
        }
        log.info(STATIC_ASSETS_FOLDER_PARAM + ": '{}'", staticAssetsFolderPath);
    }

    private void customizeDocumentRoot(ConfigurableEmbeddedServletContainer container) {
        if (!StringUtils.isEmpty(staticAssetsFolderPath)) {
            File docRoot;
            if (staticAssetsFolderPath.startsWith(File.separator)) {
                docRoot = new File(staticAssetsFolderPath);
            } else {
                final String workPath = Paths.get(".").toUri().normalize().getPath();
                docRoot = new File(workPath + staticAssetsFolderPath);
            }
            if (docRoot.exists() && docRoot.isDirectory()) {
                log.info("Custom location is used for static assets, document root folder: {}",
                        docRoot.getAbsolutePath());
                container.setDocumentRoot(docRoot);
            } else {
                log.warn("Custom document root folder {} doesn't exist, custom location for static assets was not used.",
                        docRoot.getAbsolutePath());
            }
        }
    }

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        customizeDocumentRoot(container);
    }

}

Now you can customize your app with command line or profiles (src/main/resources/application-myprofile.yml: static-assets-folder: myfolder):

> java -jar demo-0.0.1-SNAPSHOT.jar --static-assets-folder="myfolder"
> java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=myprofile

Comments

0

For Spring Boot beginners, I had a similar issue. My jQuery code was working fine within < script > tags at the bottom of my html doc (a thymeleaf template), but when I put the exact same code into an external .js doc in the static/js folder, it no longer responded. Super simple fix - just needed to put all that .js doc code inside this: $(document).ready(function () { ...code ... }); and then it worked fine. Hope this helps someone.

1 Comment

I dont think this is a proper fix. Have you debugged the issue using chrome developer's tools?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.