4

I am having a lot of issues routing my pages with Spring-Boot and AngularJS. Once the index.html page renders I get a 404 error when I click on a new link. AngularJS in loading fine, and the controllers etc are also loading.

Also worth noting I have to use this <base href="/"> when I run it on my IDE and this <base href="/personalsite/"> when I package it into a war file on deploy it on tomcat.

index.html

<html lang="en" ng-app="SharpVision">
    <head>
        <base href="/">
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />  
        <title>Drew</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="Drew's personal site" content="Drew" />
        <meta name="author" content="AHthemes" />

        <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
        <!--[if lt IE 9]>
          <!--<script src="http://a1alfred.com/sharpvisionbs3/v2/angular/assets/libs/html5shiv/html5shiv.min.js"></script>-->
          <!--<script src="http://a1alfred.com/sharpvisionbs3/v2/angular/assets/libs/respond/respond.min.js"></script>-->
        <![endif]-->
        <!--[if gte IE 9]>
          <style type="text/css">
            .gradient {
               filter: none;
            }

          </style>
        <![endif]-->

        <link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
        <link href="assets/css/styles.css" rel="stylesheet">
    </head>
    <body>

        <ng-include src="'views/structure/navigation.tpl.html'"></ng-include>

        <ng-view autoscroll="true"></ng-view>

        <ng-include src="'views/structure/footer.tpl.html'"></ng-include >

        <!--Scripts-->
        <!--<script src="bower_components/masonry/dist/masonry.pkgd.min.js"></script>-->
        <!--<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>-->
        <script src="assets/libs/flexslider/jquery.flexslider.js"></script>
        <script src="assets/libs/masonry/masonry.pkgd.min.js"></script>
        <script src="assets/libs/imagesloaded/imagesloaded.pkgd.min.js"></script>
...

app.config

app.config(function($routeProvider, $locationProvider){
    $routeProvider.when('/',{
        templateUrl: "views/misc/home.tpl.html",
        controller: "HomeController"
    })
    .when('/features/blog',{
        templateUrl: "views/features/blog.tpl.html",
        controller: "BlogController"
    })
    .when('/features/blogpost',{
        templateUrl: "views/features/blog-post.tpl.html",
        controller: "BlogPostController"
    })
    .when('/features/portfolio',{
        templateUrl: "views/features/portfolio.tpl.html",
        controller: "PortfolioController"
    })
    .when('/features/portfolioitem',{
        templateUrl: "views/features/portfolio-item.tpl.html",
        controller: "PortfolioItemController"
    })
    .when('/features/gallery',{
        templateUrl: "views/features/gallery.tpl.html",
        controller: "GalleryController"
    })
    .when('/features/404',{
        templateUrl: "views/features/404.tpl.html",
        controller: "404Controller"
    })
    .when('/features/500',{
        templateUrl: "views/features/500.tpl.html",
        controller: "500Controller"
    })
    .when('/contact',{
        templateUrl: "views/misc/contact.tpl.html",
        controller: "ContactController"
    })
    .otherwise({redirectTo:'/'});

    $locationProvider.html5Mode(true);
});

Once the page loads I select gallery:

http://localhost:8080/features/portfolioitem

at: http://localhost:8080/features/portfolioitem

which give me a 404:

404 error

However all this ONLY happens when I create a war file and deploy it on Tomcat. On my intellij IDE all I have to do it change <base href="/personalsite/"> to <base href="/"> and it works fine.

It appears once the application starts loads everything fine but handles the routing through Spring's @RestController so I tried this:

    //try mapping to contact and gallery and see what happens
    @RequestMapping(value = "/features/portfolioitem", method = RequestMethod.GET)
    public String galleryPage(){
        System.out.println("HIT HIT HIT HIT HIT!!!");

        return "personalsite/features/portfolioitem";
    }

galleryPage() renders a page but just the String personalsite/features/portfolioitem on the page.

---------------------------UPDATE 1------------------------------------

I decided to see if I could use Spring-boot `@RestController` to route my pages but that was unsuccessful. This is how I did it:

 //try mapping to contact and gallery and see what happens
    @RequestMapping(value = "/features/portfolioitem", method = RequestMethod.GET)
    @ResponseBody
    public String galleryPage(){
        System.out.println("HIT HIT HIT HIT HIT!!!");

        return "views/features/portfolioitem";
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    @ResponseBody
    public String indexPage(){
        System.out.println("I be in here too");


        return "index";
    }

WebConfig.java

@Configuration
public class WebConfig extends WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter{

    private static final Logger LOGGER = Logger.getLogger(WebConfig.class);

    @Bean
    InternalResourceViewResolver internalResourceViewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setPrefix("/webapp/");
        viewResolver.setSuffix(".html");
        return viewResolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }

}

This this only renders the string of whatever the method returns and Angular doe not load.

---------------------Update 2----------------------------

<?xml version='1.0' encoding='utf-8'?>

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

 <Service name="Catalina">

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

 <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>



</Server>

--------------------Update 3------------------------------

I added server.contextPath=/personalsite/ to my application.properties

I then change <base href="/"> to this is good because now my IDE is doing the same thing as tomcat. Index.html will render athttp://localhost:8081/personalsite/#/BUT once I click a link I get a blank page, for examplehttp://localhost:8081/features/portfolioitembutpersonalsite` is missing from the path. I add that and I get the following page:

enter image description here

5
  • When using html5mode you have to make sure your server always returns you index. Is that the case? Did you check the ui-router page? github.com/angular-ui/ui-router/wiki/… Commented Apr 11, 2016 at 21:26
  • What do your Tomcat configurations look like? If seems to me that your application's base path is not being configured correctly with Tomcat. Specifically what do your servlet mapping settings look like? Commented Apr 11, 2016 at 21:37
  • @BrunoGarcia I am using ng-route and I just removed $locationProvider.html5Mode(true); and that sadly didn't work. I also tried to add the configuration to server.xml that did not do it either. Commented Apr 12, 2016 at 14:46
  • @PeterKirby please see update 2 Commented Apr 12, 2016 at 14:49
  • Refer to github.com/spring-guides/tut-spring-security-and-angular-js/… Commented Oct 13, 2016 at 14:10

1 Answer 1

0

Update 1:

You should add 'server.contextPath=/' to your 'application.properties' file.

Update 2:

You need to remove the @ResponseBody annotation if you want Spring to resolve your view, rather than return a string, from your galleryPage method.

Update 3:

If your entire application is a single page application, with embedded templates, and you want your application, when refreshed on any valid path (like '/features/portfolioitem') to render index.html, you need to route every request to your index method. Try this:

@RequestMapping(value = "/**", method = RequestMethod.GET)
public String indexPage(){
    System.out.println("I be in here too");


    return "index";
}

This should load your index.html for all URLS. It is then up to your application to determine if the URL is valid.

Also, make sure you have $locationProvider.html5Mode(true); set in your app.

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

10 Comments

No that did not work. I even tried server.contextPath=/personalsite too
Are you using a web.xml file? If so, can you post it?
I am using angularJS so angular will configure my views on the frontend. I use spring to catch something I light needed submitted to my database like: so @RequestMapping(value = "/sendForm", method = RequestMethod.GET) public String getForm(Model model){ System.out.println("In get request"); model.addAttribute("contact", new Contact()); return "contact"; }
At least from what I read that is how it works together. There is something that happens when I create a war file that messes up my paths. However even if I correct it in my browser it gives me spring-boot error page. I guess that is a step up from a 404 at least.
Using Update 3 gives this error: Circular view path [index.html]: would dispatch back to the current handler URL [/index.html] again
|

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.