12

I am currently working with a project using SpringBoot at the backend and HTML5 and Angular 2 at the frontend.

After I deploy the project, everything works fine when I navigate in the browser, until I press reload button. Browser will show error page.

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Mon May 08 10:16:14 CDT 2017

There was an unexpected error (type=Not Found, status=404).

No message available

This is apparently being caused by the use of the HTML 5 history API to store client-side navigation in the browser URL.

So when I start to click on items on the page, I see the URL automatically appends itself.

However, this becomes a problem when refresh is hit, the full appended URL is sent to server which can't understand it because a specific mapping of that appended URL doesn't exist.

Is there a fix to this that updates the server-side configuration so that any unknown URL returns a view of the root index.html view?

For example, when I hit refresh, the URL being queried is simply the root url http://localhost:8080/root, rather than the appended URL.

This will let the browser properly navigate rather than trying to do it on the server side.

Community
  • 1
  • 1
000000000000000000000
  • 780
  • 4
  • 15
  • 47
  • "Is there a fix to this that updates the server-side configuration so that any unknown URL returns a view of the root index.html view?" — That misses the point of the History API … which is to let you have URLs that still work even if the JS completely fails (and to get better performance by having the initial page be rendered by the server instead of having to load the homepage and then run JS with Ajax requests). You might as well use hashbang URLs if you aren't going to have server rendered pages as fallback. – Quentin May 08 '17 at 15:28
  • @Quentin Thanks. Is there any way to approach it using SpringBoot? – 000000000000000000000 May 08 '17 at 16:24
  • It might on refresh/load the angular controller passing the scope to other missing service/controller. Or, it might be one or more angular or angular dependence file is either not loaded or not rendered before code execution. You may use ng-cloak. – geminiousgoel May 16 '17 at 12:14
  • You need a wildcard redirect back to `/` but I have no idea how to do it in Spring. – Aluan Haddad May 18 '17 at 01:08
  • Absolutely nothing to do with history api and Angular. – Milad May 19 '17 at 00:20

5 Answers5

3

Since it seems you are only using SpringBoot as a backend, you could either redirect all your requests to the index.html

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

  @Controller
  static class Routes {

    @RequestMapping(value = "/**", method = RequestMethod.GET)
    public String index() {
      return "index.html";
    }

  }

}

Or override the ErrorController to catch the /error you are seeing and redirect to your index instead

import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class OverrideController implements ErrorController {

  @RequestMapping("/error")
  public String index() {
    return "index.html";
  }

  @Override
  public String getErrorPath() {
    return "index.html";
  }

}

But I would recommend to separate entirely the frontend from the backend, by serving your angular app with something that could be as basic as Nginx, since you just need to serve static files. SpringBoot seems a bit overkill or not really fit for this purpose.

Here is a good configuration example you could look into for this purpose, which is basically a catch all to an index.html

server {
  server_name yoursite.com;
  root /usr/share/html;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}
ADTC
  • 8,999
  • 5
  • 68
  • 93
Preview
  • 35,317
  • 10
  • 92
  • 112
  • **Problem with using ErrorController override:** if a file was not found, instead HTTP 404, now it returns index page with HTTP 200 ... anything that relies on HTTP 404 will break - like if there was a reference to `.css.map` file, browser normally ignores if it gets 404 when trying to get the map file.. but what will it do if it gets 200 with index page instead? _Yeah..._ – ADTC Feb 05 '18 at 22:07
  • It will be better to switch to the hash location type. Go to your `environment.js` and change `locationType: 'auto'` to `locationType: 'hash'`. [Documentation about reference types is here.](https://guides.emberjs.com/v2.18.0/configuring-ember/specifying-url-type/) – ADTC Feb 06 '18 at 21:38
2

If you look at their angular tutorial there is a relevant section "Using Natural Routes":

using a simple Spring MVC controller you can naturalize the routes in your application. All you need is a a way to enumerate the Angular routes in the server. Here we choose to do it by a naming convention: all paths that do not contain a period (and are not explicitly mapped already) are Angular routes, and should forward to the home page:

@Controller
public class SpaController {
    @RequestMapping(value = "/{[path:[^\\.]*}")
    public String redirect() {
        return "forward:/";
    }
}
dave
  • 62,300
  • 5
  • 72
  • 93
0

Actually I am also getting the same problem in previously, My Project running with gulp Serve and at Localhost should be working,but at the deploy the code at server with out refershing its working once its refresh it shows the not found the path at the Time I have an idea among with the location loading at main routing giving extra '#' Like

suppose the path is 202.168.09.01/Myproject/myservice this kind of path can be change like 202.168.09.01/#/Myproject/myservice

So The # will getting actual total path of the location

I am done the issue In Angularjs, Html5.

Naveen Kumar
  • 50
  • 1
  • 8
0

I think the others are pretty good in their answers that uses natural routes, so I won't go into too much detail here.

But to answer the question of why your index.html doesn't show up, I think I have found the answer here

So basically the answer explained it this way concerning Spring Boot: "Spring Boot docs also says:

Do not use the src/main/webapp directory if your application will be packaged as a jar. Although this directory is a common standard, it will only work with war packaging and it will be silently ignored by most build tools if you generate a jar.

Spring Boot is very opinionated and works best when you do not try to resist defaults. I don't see any reason having your files placed in /src/main/webapp. Just use /src/main/resources/static for your front-end assets. That is most common place.

It will serve these static files from root URI automatically, without need to create any root level Controller. In fact your IndexController would prevent static front-end files to be served from root URI. There is no need to create Controller for static files at all.

Also view resolver is not needed for your app. Your app is just REST API consumed by single page angular application. So your HTML templating is on client. View resolvers are needed if you are doing server side HTML templating (e.g. with Thymeleaf or JSP). So remove that piece also."

I believe that you were asking about using Spring Boot, and after research on the subject for it, I believe this should be applied to you.

0

This happens as by default Angular is using HTML5 routing strategy. If you change the routing strategy to hash routing strategy then this will not happen. Just add "useHash: true" where you imported the RouterModule and you are all set.

RouterModule.forRoot(routes, {useHash: true})
Unheilig
  • 16,196
  • 193
  • 68
  • 98
Arsalan Siddiqui
  • 181
  • 2
  • 11