[FIXED] Spring Boot with redirecting with single page angular2

Issue

I have a single page Angular app with Spring Boot. It looks like the following:

src
  main
  java
    controller
       HomeController
       CustomerController
       OtherController
  webapp
    js/angular-files.js
    index.html

Spring boot correctly defaults to webapp folder and serves index.html file.

What I am looking to do is:

  1. For every local REST request not starting with /api overwrite and redirect to default webapp/index.html. I plan to serve anything /api to the spring controllers.

  2. Is there a way to prefix all controllers with API so that I do not have to write API every time?
    e.g.

    @RequestMapping(“/api/home”) can write shorthand in code @RequestMapping(“/home”)

or

@RequestMapping("/api/other-controller/:id") can write shorthand  @RequestMapping("/other-controller/:id")

I’m looking for every API request, e.g. 1) http://localhost:8080/api/home keep API with API and resolve to correct controller and return JSON, however if someone enters a URL like http:///localhost/some-url or http:///localhost/some-other/123/url then it will serve the index.html page and keep the URL.

enter image description here

Alternative ways to do it: try adding #ErrorViewResolver:
Springboot/Angular2 – How to handle HTML5 urls?

Solution

For every local REST request not starting with /api overwrite and redirect to default webapp/index.html. I plan to serve anything /api to the spring controllers.

Update 15/05/2017

Let me re-phrase your query for other readers. (Correct me, if misunderstood)

Background
Using Spring Boot and Serving static resources from classpath

Requirement
All 404 non api requests should be redirected to index.html.

NON API – means Requests in which URL doesn’t start with /api.
API – 404 should throw 404 as usual.

Sample Response
/api/something – will throw 404
/index.html – will server index.html
/something – will redirect to index.html

My Solution

Let the Spring MVC throw exceptions, if any handler is not available for the given resource.

Add following to application.properties

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

Add a ControllerAdvice as follows

@ControllerAdvice
public class RedirectOnResourceNotFoundException {

    @ExceptionHandler(value = NoHandlerFoundException.class)
    public Object handleStaticResourceNotFound(final NoHandlerFoundException ex, HttpServletRequest req, RedirectAttributes redirectAttributes) {
        if (req.getRequestURI().startsWith("/api"))
            return this.getApiResourceNotFoundBody(ex, req);
        else {
            redirectAttributes.addFlashAttribute("errorMessage", "My Custom error message");
            return "redirect:/index.html";
        }
    }

    private ResponseEntity<String> getApiResourceNotFoundBody(NoHandlerFoundException ex, HttpServletRequest req) {
        return new ResponseEntity<>("Not Found !!", HttpStatus.NOT_FOUND);
    }
}

You can customize the error message as you like.

Is there a way to prefix all controllers with api so that I do not have to write api every time.

For this, you can create a BaseController and set the RequestMapping path to /api

Example

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/api")
public abstract class BaseController {}

And extend this BaseController and make sure you do not annotate child class with @RequestMapping

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FirstTestController extends BaseController {
    @RequestMapping(path = "/something")
    public String sayHello() {
        return "Hello World !!";
    }

}

Previous Answer

You can create a Filter which redirects to /index.html if request path doesn’t startsWith /api.

// CODE REMOVED. Check Edit History If you want.

Answered By – ansh

Answer Checked By – Mary Flores (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published