So I am trying to host a Single Page Application alongside a normal REST API with spring.
What this means is that all requests that goes to the normal /api/
endpoints should be handled by the respective controller and all other requests should be directed to the resources in the folder /static/built
I have gotten this to work by catching all NoHandlerFoundExceptions
and redirecting to either the js
file or the html
file. And then used a WebMvcConfigurer
to map the static content.
But this all seems like a hack to me, so is there a less hacky way of doing it?
Managed to have React+ReactRouter app working by adding following mapping:
@Controller
public class RedirectController {
@GetMapping(value = {"/{regex:\\w+}", "/**/{regex:\\w+}"})
public String forward404() {
return "forward:/";
}
}
This was inspired by https://stackoverflow.com/a/42998817/991894
The easiest way I get my SPAs to work with a Spring backend API is to have 2 different controllers: one for the root index page of the SPA and the other controller is used to manage various RESTful API endpoints:
Here are my two controllers:
MainController.java
@Controller
public class MainController {
@RequestMapping(value = "/")
public String index() {
return "index";
}
}
MonitoringController.java
@RestController
@RequestMapping(value = "api")
public class MonitoringEndpoints {
@GetMapping(path = "/health", produces = "application/hal+json")
public ResponseEntity<?> checkHealth() throws Exception {
HealthBean healthBean = new HealthBean();
healthBean.setStatus("UP");
return ResponseEntity.ok(healthBean);
}
}
Notice how the API endpoint controller utilizes the '@RestConroller' annotation while the main controller utilizes the '@Conroller' annotation. This is because of how Thymeleaf utilizes it's ViewResolver. See:
Spring Boot MVC, not returning my view
Now go ahead and place your index.html page at src/main/resources/templates/index.html because Spring by default looks for your html pages within this location.
My index.html pages looks like this:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8"/>
<title>EDP Monitoring Tool</title>
</head>
<body>
<!-- Entry point to our ReactJS single page web application -->
<div id="root"></div>
<script type="text/javascript" src="built/bundle.js"></script>
</body>
</html>
Not sure how you're wiring up your frontend, whether that is a ReactJS app or something but I believe this information would be helpful for you. Let me know if I can answer additional questions for you.
In addition, if you're using Webpack, you can set up the entry point of your JS files via the webpack.config.js file under the entry key so like so:
entry: ['./src/main/js/index.js']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With