javareactjsspring-bootmavenapache-tomee

React routes not working in spring boot maven project on TomEE server


Im trying to host a react app with a spring project on a tomEE server. I'm having some problems with the react routes on the server. It works fine locally when running the react app and sprint app, but only the root path (/) works on the server. There are no error messages in the server logs.

The 404 error seems to be coming from spring: 404 error message

This is the controller class:

@CrossOrigin
@RestController
@RequestMapping("api")
public class DemoController {
    @GetMapping("/demo")
    public List<String> demo(){
        List<String> list = new ArrayList<>(Arrays.asList("Hello", "World", "from", "Spring!"));

        return list;
    }
}

The react App.js:

import {Route, Routes} from "react-router-dom";
import Test from "./components/test";


function App() {
  return (
      <Routes>
          <Route index element={<Test />} />
          <Route path="test" element={<div>Test</div>} />
      </Routes>
  );
}
export default App;

The index.js:

...
import {BrowserRouter} from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
      <BrowserRouter basename={process.env.PUBLIC_URL}>
          <App />
      </BrowserRouter>
  </React.StrictMode>
);

env.local: PUBLIC_URL=.

env.production: PUBLIC_URL=/Expo-project-0.0.1-SNAPSHOT

Scripts in package.json:

  "scripts": {
    "start": "react-scripts start",
    "build": "env-cmd -f ./.env.production react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }

pox.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>no.hvl.dat109</groupId>
    <artifactId>Expo-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>Expo-prosject</name>
    <description>Expo-prosject</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

I have tried adding a trailing slash in the .env files. Using hashroutes instead of browserroutes. Changing the controller to point at the index file. But we might have done something wrong here, because i think the problem is related to the routes not pointing to the index.html at all time.


Solution

  • I found a solution. As you said the 404 error is caused by spring and not react. You want all routes except /api to point to your react index.html file.

    To solve this I created a new controller. In this case i called it Controller.java, and paste the code below.

    @org.springframework.stereotype.Controller
    public class Controller {
        @RequestMapping(value = { "/", "/{x:[\\w\\-]+}", "/{x:^(?!api$).*$}/*/{y:[\\w\\-]+}","/error"  })
        public String index() {
            return "index.html";
        }
    }
    

    This code redirects all requests except /api to the index.html file using regex.