4

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:

warning

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?

3
  • same issue - I believe you are also trying out the tutorial from bbachi github.com/bbachi/angular-java-example Commented Feb 6, 2022 at 6:44
  • Hey, could be, I don't quite remember it anymore. I solved the issue but it's a long time ago, but what I could find in my code / remembered I have posted as answer now. Good luck! Commented Feb 7, 2022 at 12:17
  • I got the fix from another stackoverflow page, remove the default path "/" forwarding completely from code, make sure @EnableWebMVC annotation is not used and your Single Page Application (index.html) files are kept in "resources/public" path. SpringBoot automatically handles it :) Commented Feb 9, 2022 at 5:08

2 Answers 2

2

Narrowing down the ResourceHandler paths was the right approach:

registry.addResourceHandler(
        "/login/**",
        "/all other Uris of my website"
).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");
            }
          });

There was another problem that kept returning 404 for the other URIs, but that had nothing to do with the resourceHandler, but was a problem at our Gateway.

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

Comments

0
  1. Make sure no default path "/" is configured in your SpringBoot code/controller's
  2. Ensure you are not using @EnableWebMvc annotation anywhere in your app
  3. 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.

2 Comments

This does not work if the url is directly accessed or a page with a deeper url refreshed.
Whats the error or have you been able to find a better solution - kindly share to all

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.