We have an application built with ReactJS and Spring Boot backend. Currently, we use the following controller to forward requests to React routers:
@Controller
public class ReactAppController {
@GetMapping(value = { "/**/{path:[^\\.]*}", "/{path:^(?!\\/api\\/).*}", "/{path:^(?!/process\\/).*}" })
public String forward() {
return "forward:/";
}
}
From my understanding, this controller handles frontend requests and resolves them to specific React routes. (I have limited React knowledge, but this is how it currently functions.)
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
App.js
...
return (
<div className="App">
<Helmet>
<meta charSet="utf-8" />
<title>MyStore</title>
<link rel="canonical" />
<meta name="description" content="Helmet application" />
</Helmet>
<Routes>
<Route
exact
path="/pos/country"
element={<Countrylist />}
/>
<Route
exact
path="/hq/country"
element={<HQCountrylist />}
/>
<Route
exact
path="/pos"
element={<Storelist />}
/>
...
We are facing below challeges while migrating this application to Spring Boot 3.x
Challenges :
- Path Pattern Error
It seems AntPathMatcher
has been deprecated and replaced with PathPatternParser
in latest version of Spring, causing the following error due to an invalid pattern:
"description": "Invalid mapping pattern detected:\n/**/{path:[^\\.]*}\n^\nNo more pattern data allowed after {*...} or ** pattern element",
"action": "Fix this pattern in your application or switch to the legacy parser implementation with 'spring.mvc.pathmatch.matching-strategy=ant_path_matcher'.",
"throwable": {
"class": ".springframework.web.util.pattern.PatternParseException",
"msg": "No more pattern data allowed after {*...} or ** pattern element"
}
To work around this, I hardcoded the pattern like this, which allows path matching and execution of the forward() method:
@Controller
public class ReactAppController {
@GetMapping(value = { "/{path:[^.]*}", "/*/{path:[^.]*}", "/*/*/{path:[^.]*}", "/*/*/*/{path:[^.]*}",
"/{path:^(?!\\/api\\/).*}", "/{path:^(?!/process\\/).*}" })
public String forward() {
return "forward:/";
}
}
Request for Input: Is there a cleaner way to handle this path matching without resorting to hardcoding multiple patterns?
- View Resolver Issue
Since we are migrating application to Webflux (earlier MVC), it was erroring out that No View Resolver bean defined. To address this, we explicitly created a ThymeleafReactiveViewResolver bean:
@Bean
public ThymeleafReactiveViewResolver thymeleafReactiveViewResolver(ISpringWebFluxTemplateEngine templateEngine) {
ThymeleafReactiveViewResolver viewResolver = new ThymeleafReactiveViewResolver();
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
However, we encountered the following error, indicating that forwards are not supported:
"throwable": {
"class": "java.lang.UnsupportedOperationException",
"msg": "Forwards are not currently supported by ThymeleafReactiveViewResolver",
"stack": [
".thymeleaf.spring6.view.reactive.ThymeleafReactiveViewResolver.resolveViewName(ThymeleafReactiveViewResolver.java:984)"
]
}
Using a redirect works, but it forces a client-side request, and the respective React router function does not get triggered.
Request for Input: How can we make this forward work in a WebFlux setup? Are there alternative solutions to achieve the same behavior?
Any insights or suggestions would be greatly appreciated.
Thanks.