26

I'm currently needing to serve my React app with Spring Boot. It is working for the root url - localhost:8080/, but of course none of the sub-routes are recognized by the Spring Controller.

I'm not sure how to get the React Routing and Spring request mapping to line up without hard-coding in every possible route to map to index.html - and then some of the routes have variable sub-routes.


Here is my HomeController that serves the index.html

@Controller
public class HomeController {

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

Here is the Routing render in my React App

const Root = ({ store }) => (
  <Provider store={store}>
    <Router history={browserHistory}>
      <Route path="/" component={App}>
        <IndexRedirect to="users"/>
        <Route path="/org" component={OrgSearch}>
          {<Route path="/org/:orgId" component={Org}/>}
        </Route>
        <Route path="/users" component={UserSearch}>
          {<Route path="/users/:userId" component={User} />}
        </Route>
      </Route>
    </Router>
  </Provider>
)

Any help is greatly appreciated!


EDIT: I tried adding some wildcard functionality, and it is presenting some strange behavior. Here is the updated code for the HomeController.

@Controller
public class HomeController {

    @RequestMapping(value = {"/", "/users/**", "/org/**"})
    public String index() {
        return "index.html";
    }
}

I can access / and /users but not /users/ or /users/2545.

Here is the error when I try to access the latter.

2017-04-14 09:21:59.896 ERROR 58840 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Circular view path [index.html]: would dispatch back to the current handler URL [/users/index.html] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)] with root cause

javax.servlet.ServletException: Circular view path [index.html]: would dispatch back to the current handler URL [/users/index.html] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
    at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:205) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:145) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980) ~[spring-webmvc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
qbolt
  • 543
  • 3
  • 10
  • 17

3 Answers3

20

For me, I tried the answer in this link. I did not have a controller.

Basically it is about defining the addViewController...

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
      registry.addViewController("/{spring:\\w+}")
            .setViewName("forward:/");
      registry.addViewController("/**/{spring:\\w+}")
            .setViewName("forward:/");
      registry.addViewController("/{spring:\\w+}/**{spring:?!(\\.js|\\.css)$}")
            .setViewName("forward:/");
  }
}
Łukasz K
  • 562
  • 6
  • 10
Fadd
  • 770
  • 2
  • 8
  • 19
1

I had the same issue, and this mapping worked for me:

@RequestMapping(value = {"/","/users/{id}"})
1

I had a similar problem and solved it with separation of URLs with '**' into separate annotated methods like:

@Controller
public class HomeController {

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

    @RequestMapping(value = {"/users/{**}"})
    public String users() {
        return "/";
    }

    @RequestMapping(value = {"/org/{**}"})
    public String org() {
        return "/";
    }
}
  • This post is a bit old but I am hitting the same issue. If I return "index.html" , I actually get text "index.html" on the browser. I do have react's packaged index.html in the static folder. Not sure what am I missing here ? – user1805280 Sep 30 '21 at 06:39