4

I have Spring Boot Application (backend) and for the Frontend I am using the Angular 2 Single Page Application.

Whenever I navigate to a route for example: localhost:8080/getAccounts and do after the navigation a refresh I get the Whitelabel Error Page. If I am at the root localhost:8080 I works fine. The problem only occurs in the sub links.

Returning (use the return/back button) to the previous page also works fine. Just the refresh.

I also can not call direct the link: localhost:8080/getAccounts. First I have to go to Home (localhost:8080) an call the page throug sub navigation bar.

Does anybody had the same problem? What excalty I do have to change. My Code:

Main.ts

import {bootstrap} from '@angular/platform-browser-dynamic';
import {AppComponent} from './components/app.component';
import {HTTP_PROVIDERS};
import {enableProdMode} from '@angular/core';

enableProdMode();
bootstrap(AppComponent, [HTTP_PROVIDERS]);

app.comonent:

import { Component, OnInit } from '@angular/core';

import { Http } from '@angular/http';
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';

import { HomeComponent } from './home.component';
import { UserSearchComponent} from './webUserProfiles.component';
import { UserDetailViewComponent} from './webUserProfileView.component'; 

import { HTTPService } from '../service/http.service';


@Component({
  selector: 'app-content',
  templateUrl: './app/templates/app.component.html',
  directives: [ROUTER_DIRECTIVES, AccessErrorComponent],
  providers: [
    ROUTER_PROVIDERS,
    HTTPService
  ]
})

@RouteConfig([
  {
    path: '/',
    name: 'HomeComponent,
    useAsDefault: true
  },
  {
    path: '/user',
    name: 'UserSearch',
    component: UserSearchComponent,
  },
  {
    path: '/user/:id',
    name: 'UserDetailView',
    component: UserDetailViewComponent,
  }
])

export class AppComponent implements OnInit {
    constructor (
    ) { } 
}
}

Thanks in advance

trap
  • 2,550
  • 7
  • 21
  • 42

4 Answers4

5

After some researches, i found this pretty good answer from Thierry Templier

With the default strategy (HTML5 history API) of routing, you need a server configuration to redirect all your paths to your HTML entry point file. With the hashbang approach it's not necessary... If you want to switch to this approach, simply use the following code:

import { bootstrap } from "angular2/platform/browser";
import { provide } from "angular2/core";
import {
  ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy
} from "angular2/router";

bootstrap(MainApp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass:HashLocationStrategy});
]);

You could have a look at these questions about this issue:

Community
  • 1
  • 1
Leogout
  • 1,187
  • 1
  • 13
  • 32
  • First of all thank you for the answer. The Routing (Router_providers) is in my application in the app.component, and not in the main.ts. In the main.ts I only have bootstrap(MyApp, [HTTP_PROVIDERS]); and no ROUTER_PROVIDERS. Does it make any difference? – trap Aug 12 '16 at 10:47
  • Just a heads up to anyone considering implementing this strategy: the angular documentation specifically warns against using the hash routing strategy if you intend on using any server-side rending to speed up load times. Hash routes would prevent that from working. https://angular.io/guide/router#appendix-locationstrategy-and-browser-url-styles – David Sep 20 '17 at 14:10
  • I am having the same issue with react application running in spring cloud gateway. The home is fine, the subpages when clicked from the home page works fine, but when I add the route in the browser address bar I get the white label error 404 – manjosh Jan 01 '23 at 09:10
3

I had a similar issue WhiteLabel Error message on my Angular SPA whenever I did a refresh.

If you don't want to change the app URL (which will happen if you use HashLocation Strategy), you could add a new controller to handle the White label Error mapping in your Spring Boot app.

The fix was to create a controller that implements ErrorController and return a ModelAndView object that forwards to /

@CrossOrigin
@RestController
public class IndexController implements ErrorController {
    
    private static final String PATH = "/error";
    
    @RequestMapping(value = PATH)
    public ModelAndView saveLeadQuery() {           
        return new ModelAndView("forward:/");
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}
  • Nice shortcut, easier than setup rewrite rules on tomcat – Camille Jan 14 '21 at 13:12
  • This works like a charm!! But I am not able to figure out how the forward:/ is happening. When inspect in browser I did not see and redirect/forward calls. Also in my case the current page was reloaded instead of loading the "/" page – mAsK Dec 14 '21 at 04:26
  • The forward:/ statement instructs Spring MVC to internally forward the request to the root path ("/"), effectively handling the request within the same server-side request context without a full browser redirect. – Hoang Duc Nguyen May 27 '23 at 08:45
1

If you don't want to use the HashLocationStrategy, you can add the following controller in your project :

@Controller
public class UiController {

    @GetMapping("/")
    public String welcome() {
        return "index.html";
    }

    // Match everything without a suffix (so not a static resource)
    @GetMapping(value = {
            "/{path:[^.]*}",
            "/{path:[^.]*}/{path:[^.]*}",
            "/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}",
            "/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}",
            "/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}/{path:[^.]*}"
            // add more if required ...
    })
    public String redirect() {
        // Forward to home page so that route is preserved.
        return "forward:/";
    }

}
Paul EDANGE
  • 131
  • 1
  • 5
0

Have one better way...
You can implement WebMvcConfigurer and add the view controller generic paths.
follow the example:

package net.mypackage.config;

import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration public class MvcConfig implements WebMvcConfigurer {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    String viewName = "forward:/";

    registry.addViewController("/{spring:\\w+}")
            .setViewName(viewName);
    registry.addViewController("/**/{spring:\\w+}")
            .setViewName(viewName);
    registry.addViewController("/{spring:\\w+}/**{spring:?!(\\.js|\\.css)$}")
            .setViewName(viewName);
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}

}

About the macther: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html