Issue
I have a Spring Boot app and an Angular app. I want to serve the Angular App from the Spring Boot App. I build the Angular App and moved all files, including the index.html file, into /resources/static/ and just to be sure also to resources/public/. I also put the index.html into resources/templates. I received 404 when calling any of the angular routes e.g. mywebsite.com/login
Then I added a controller to forward all requests to my Angular App:
@Controller
public class RedirectToAngularController {
/**
* Should redirect all routes to FrontEnd, but doesn't work.
*/
@RequestMapping({"/", "/login", "/login/**"})
public String redirectLogin() {
log.info("Forwarding request to Angular (index.html)");
return "forward:/index.html";
}
}
IntelliJ gives me a warning for "forward:/index.html" that it can't find the URL:
I still deployed my website and open it at myWebsite.com/login
or myWebsite.com/confirm
. Instead of my index.html file getting displayed I see forward:/index.html
as a string in my browser. So it actually returns the string, not the file
In the logs "Forwarding request to Angular (index.html)" appears, but then it says: Cannot find GET /index.html
in the next line.
So I deleted that controller and instead tried to solve this with a ResourceHandler:
@Configuration
public class WebAdapterConfig 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");
}
});
registry.setOrder(-1);
}
}
This was described here: Springboot/Angular2 - How to handle HTML5 urls? and also here: https://keepgrowing.in/java/springboot/make-spring-boot-surrender-routing-control-to-angular/
But this redirects everything! I now get the index file when I open mywebsite.com/login as well as when I make a postman request to my api (e.g. GET mywebsite.com/api/users)
So I tried to narrow it down by replacing registry.addResourceHandler("/**/*")
with registry.addResourceHandler("/login")
or registry.addResourceHandler("/login/**", "/confirm")
. But then only mywebsite.com/login/something and mywebsite.com/confirm retrun the index.html, but all other paths, including the URI for the api methods return 404!
A third approach was to add view controller:
@Configuration
public class WebAdapterConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("forward:/index.html");
registry.addViewController("/login/**").setViewName("forward:/index.html");
registry.addViewController("/confirm").setViewName("forward:/index.html");
}
}
But then I always received 404 for all routes.
I also added spring web MVC to my dependencies, but this didn't seem to change anything.
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
}
p.s. I don't use tymeleaf as my files are coming from angular. Maybe that's why forward:/
doesn't work?
Solution
- Make sure no default path "/" is configured in your SpringBoot code/controller's
- Ensure you are not using @EnableWebMvc annotation anywhere in your app
- put all your UI files in the "../resources/public" folder (mainly your index.html shall be on this path)
This should resolve your issue's in general :)
SpringBoot automatically detects this and works well for all sorts of Single-page applications.
Answered By - Abdeali Chandanwala
Answer Checked By - Pedro (JavaFixing Volunteer)