In a multi module application Spring Boot should surrender routing control to Angular, otherwise trying to access any route other than the root page will result in a Whitelabel Error Page:
"There was an unexpected error (type=Not Found, status=404)"
All paths supported by Angular are accessible when the app server is started with the following command:
1 |
$ ng serve |
However, when you build the whole project with Maven and run it, the app will break cause the Spring Boot will still be trying to manage paths by itself.
While the root path (e.g. http://localhost:8080/
) will still work, accessing any other route (e.g. http://localhost:8080/dashboard
) will give you the following error:
To fix it, you have to customize the MVC Configuration.
In a project built with Spring Boot 2.0.4
you can create a config
directory and the MvcConfiguration
class in it. The following code is responsible for redirecting all requests to the index.html
– as a result, your Angular app will be able to handle them:
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 |
// spring-boot-angular-scaffolding/backend/src/main/java/in/keepgrowing/springbootangularscaffolding/config/MvcConfiguration.java package in.keepgrowing.springbootangularscaffolding.config; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.PathResourceResolver; import java.io.IOException; @Configuration public class MvcConfiguration implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**") .addResourceLocations("classpath:/static/") .resourceChain(true) .addResolver(new PathResourceResolver() { @Override protected Resource getResource(String resourcePath, Resource location) throws IOException { Resource requestedResource = location.createRelative(resourcePath); return requestedResource.exists() && requestedResource.isReadable() ? requestedResource : new ClassPathResource("/static/index.html"); } }); } } |
The "/**"
path pattern will be matched by AntPathMatcher to zero or more directories in a path, so this configuration will be applied to all routes in our project. Next, a resolver – created with dependency to PathResourceResolver – will try to find a resource under the given location and all requests that are not handled by Spring Boot will be redirected to index.html
allowing Angular to take care of them.
Remember to add @Configuration annotation and to implement the WebMvcConfigurer interface. |
You can check out my example Angular Spring Boot scaffolding project and inspect the code from this post in the commit 3a57e01056c8183d87a9eb167aebd7994d23d55f.
This solution is based on this StackOverflow answer.
Photo by Matthew Henry on StockSnap
how to load 2 angular apps inside static folder?
I Love you, your so smart. now angular routing is working in spring boot tomcat deployment.
For my case, angular is dealing the routing part. I do not get any white page error.
Thank you for providing the solution, I tried all of different solutions but none of them worked, this one worked like a charm.
Hi \o Thank you for sharing this solution. Worked great for me using Spring Boot 2.3.3 and Angular 10!