2
votes

I am struggling with an issue where spring-boot isn't serving front-end files(created through angular) on 8080. I ran ng build that converted .ts ng component files to .js and generated in outputPath:/resource/static folder( I set outputPath in angular.json file). Created a controller to serve content from resources/static.

    @Controller
    public class AppController {
        @GetMapping("/")
        public String index() {
            return "index";
        }
     }

main class (src/mainjava/webapp/app):

@Configuration
@EnableAutoConfiguration
@ComponentScan({"webapp"})
public class Application extends WebMvcAutoConfiguration {

    public static void main(String[] args) {
    SpringApplication app = new SpringApplication(Application.class);
    app.run(args);
}
}

Ran ng build --base-href . generates files as shown in below image.

index.html :

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Welcome app</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
<script type="text/javascript" src="runtime.js"></script><script type="text/javascript" src="polyfills.js"></script><script type="text/javascript" src="styles.js"></script><script type="text/javascript" src="vendor.js"></script><script type="text/javascript" src="main.js"></script></body>
</html>

Note: This is a gradle project.Front-end code resides in : src/main/java/webapp/frontend dir

Application.yml in /resources

server:
  servlet:
    context-path: /
  port: 8080

On tomcat start:

Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-09-13 12:45:34.372  INFO 96027 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-09-13 12:45:34.384  INFO 96027 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in exceptionHandle
2018-09-13 12:45:34.405  INFO 96027 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2018-09-13 12:45:34.566  INFO 96027 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-09-13 12:45:34.568  INFO 96027 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-09-13 12:45:34.575  INFO 96027 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-09-13 12:45:34.620  INFO 96027 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''

I even tried adding html file under /resources to see if tomcat serves any contents from this folder. I can't access page1.html as well so not sure how would angular/ng content be different that it can't serve when tomcat is up and running.

resources/static

Do I need any other configuration to have spring-boot serve angular frontend code? Any suggestion is appreciated.

@DavidT Answers to your Ques:

  • Yes in build.gradle:compile('org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASE')

  • static content here: MYPROJECT/MYPROJECT-web/src/main/resources/static/

  • Since spring-boot didn't pick angular static content from path, I referred online resources that suggested to add a controller specifically to serve it. [I have 3 ng components accessible- login: http://localhost:4200/,home: http://localhost:4200/home,sale:http://localhost:4200/sale. But to access on tomcat port I thought to put files under static; rest angular will take care of routing.]

  • When run ng build from frotnend dir, generates angular files under frontend/src dir. Either I can manually copy, paste manually to put in static folder or change outputPath to point to resources/static in angular.json which directly put it there on running ng build cmd. Exact files in above resources/static screenshot.

  • I haven't used javascript console but opening index.html with browser option from IntellijIdea, inspect on webpage I see error-

Refused to execute script from '' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

Replacing <script type to "text/html" removes these errors from inspect but still no UI on http://localhost:8080/.

The strange part is when I pasted the same index.html file from that demo project to mine in static folder, it doesn't display anything when browsed to http://localhost:8080. But noticed when open this file from browser option in IntellijIdea (this URI in browser: http://localhost:63342/MY-PROJ/MY-PROJ-WEB-main/static/index.html , then it shows the content

Is <base href="/"> an issue or scripts tags?

4

4 Answers

1
votes

Steps to success without being complicated like in the link above:

  1. Went to https://start.spring.io/
  2. Selected a gradle project
  3. Added Web dependency
  4. Downloaded and unarchived the result (didn’t change name from demo)
  5. Create: demo/src/main/resources/static/index.html with the following contents:
    <html><body>YOU ARE IN!</body></html>
  6. Issue the following in the demo directory to run your application: ./gradlew bootRun
  7. Open a browser and go to http://localhost:8080/

You now have proof that putting something into MY PROJECT/src/main/resources/static/ will produce the contents of your HTML file.

So I have the following questions:

  • Did you add SpringMVC into your spring boot project using something like compile('org.springframework.boot:spring-boot-starter-web')?

  • Did you put your static content into MY PROJECT/src/main/resources/static/?

  • Why do you need a controller to serve static content if one is provided for you? Especially one that is mapped to /?
  • Is angular putting *.html files into MY PROJECT/src/main/resources/static/?
  • What does the javascript console say? Is runtime.js found?

Please see https://spring.io/guides/gs/serving-web-content/ in section Add a Home Page

Please see https://stackguides.com/questions/24661289/spring-boot-not-serving-static-content content for other ideas of what not to do (and why).

This was originally posted on https://www.quora.com/How-can-spring-boot-serve-angular-static-files/answer/David-Talalayevsky

0
votes

This is because you are using the @RestController annotation that implicitly includes @ResponseBody. You must use @Controller for Spring boot to automatically load a html template.

@Controller
public class AppController {
    @GetMapping("/")
    public String index() {
        return "index";
    }
 }
0
votes

On Controller method try to put @RequestMapping annotation just an suggestion

Like this:

@Controller
@RequestMapping("/")
public class AppController{ 
 }

And on ComponentScan (basepackages{"com.packagename of modal classes"})

0
votes

It happens because spring try to process you requests and it not understand that they should go to static. Try to add following config:

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/ui/**").setViewName("/");
    }
}

where addViewController("/ui/**") it is pattern for accessing you angular pages