Create fullstack Web Application with Spring Boot and Next.js
Published: 2023-10-24 16:54:57

Crafting a web application is a meticulous art, and I've found my preferred canvas in the fusion of Next.js for the frontend and a robust Spring Boot backend. Next.js has captured my heart due to its efficient frontend development capabilities. With Next.js, the canvas is yours to paint, allowing you to craft full-stack applications enriched with your unique API.

However, the journey isn't without its nuances. There are moments when the harmony of integrating static assets with your backend application becomes crucial for a seamless user experience.

That's where this guide comes in. It's dedicated to teaching you the art of seamlessly serving static assets from a Next.js application within a Spring Boot environment. Our main objective is to tackle the challenges of browser refreshes and direct URL entries, ensuring a fluid user experience within the Tomcat server, all while making the most of Next.js's static resources.

If you're eager to delve into the intricacies of [creating a full-stack web application with Spring Boot and Next.js](https://www.e3docs.com/blog/creating-a-full-stack-web-application-with-spring-boot-and-next-js/), this article is your compass to navigate the journey.

## Create a Nextjs app with the following command

```
npx create-next-app@latest
```
This command sets up a new Next.js project with the latest version, providing you with a solid foundation for building the front end.

Once the Next.js project is created, open it in your preferred text editor, such as Visual Studio Code. This will allow you to work with the front-end code and make necessary modifications.

Make necessary changes in package.json & next.config.js and build the project

## Fetch Data from the Backend
Create a list.js file in the Next.js project responsible for fetching data from the Spring Boot API. Implement the necessary logic to retrieve data from the backend and render it in the front end.

```
function List() {
    const [list, setList] = useState([])
    const fetchList = () => {
        fetch("/e3docs/getlist")
            .then(response => {
                return response.json()
            })
            .then(data => {
                setList(data)
            })
    }
    useEffect(() => {
        fetchList()
    }, [])
    function getlist() {
        return list.map((item, i) => {
            return (
                <Fragment key={i}>
                    <tr>
                        <td>
                            {(i + 1)}
                        </td>
                        <td>
                            {item}
                        </td>
                    </tr>
                </Fragment>
            );
        })
    }
    return (
        <main>
            <div style={{ paddingLeft: '34%', paddingTop: '2%', display: 'flex' }}>
                <h2 style={{ paddingRight: '10px' }}>
                    <Link href="/">Home</Link>
                </h2>
                <h2>
                    <Link href="/list">List</Link>
                </h2>
            </div>
            <div style={{ paddingLeft: '34%', paddingTop: '3%' }}>
                <table>
                    <thead>
                        <tr>
                            <th>No.</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        {list.length > 0 && (getlist())}
                    </tbody>
                </table >
            </div>
        </main>
    );
}
export default List;
```

## Create a New Page to Handle Web App Refresh and Direct URL Entry
To handle scenarios like web app refresh or direct URL entry, create a new page in the Next.js project. This page will help to handle the 404 error page in Next JS when the user enters a direct URL into the browser or the page refreshes.

```
function PageRefresh() {
    const router = useRouter();
    useEffect(() => {
        if (router.isReady) {
            router.push(router.asPath).catch((e) => {
                router.push('/_error');
            });
        }
    }, [router.isReady])
    return (
        <div>Loading...</div>
    );
}
export default PageRefresh;
```
Build and export a Next.js project that will create an “out” folder with the compiled and optimized Next.js application.

## Create a New Project with Spring Initializr
Use [Spring Initializr](https://start.spring.io/) to create a new Spring Boot project. Specify the necessary dependencies and project settings, and generate the project structure.

After generating the project, locate the build.gradle file and update it with any additional dependencies or plugins required for your application. This file serves as the configuration for your build system.

## Create a Controller Class for API
To handle API requests, create a controller class in your Spring Boot project. This class will define the endpoints and their associated request-handling methods, allowing you to interact with your backend API.

```
@RestController
@RequestMapping("e3docs")
public class E3DocsController {
 @GetMapping("/getlist")
 public List<String> getList() {
  List<String> list = new ArrayList<String>();
  list.add("India");
  list.add("China");
  list.add("United States(US)");
  list.add("Russia");
  list.add("Australia");
  list.add("African");
  list.add("Europe");
  return list;
 }
}
```

## Create a Filter Component for Next.js Integration
For smooth integration between the Spring Boot backend and the Next.js frontend, create a filter component. This component will intercept requests and perform necessary actions like direct URL entry or page refresh.

```
@Component
public class PageRefreshFilter implements Filter {
    private static final String PAGE = "/pagerefresh/pagerefresh.html";
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
    }
    private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        String path = request.getServletPath();
        if ("/".equals(path) || path.contains(".") || path.contains("e3docs")) {
            chain.doFilter(request, response);
        } else {
            request.getRequestDispatcher(PAGE).forward(request, response);
        }
    }
}
```

## Integrate the Frontend with the Backend
Copy the static content from the “out” folder of the Next.js project into the Spring Boot project’s /src/main/resources/static folder. This ensures that the frontend assets are accessible from the Spring Boot server.

Build the Spring Boot project by running the following command:
`gradlew clean assemble`

Upon successfully completing the build process, you’ll locate a zip file within the “build/distributions” directory. Extract the contents of this zip file and execute the relevant script, such as a batch file (e.g., .bat), to initiate the Spring Boot server.

Once the server is operational, you can access the application by opening your web browser and entering the following URL: **http://localhost:8080**. This will allow you to interact with your Spring Boot application seamlessly.

For a detailed walkthrough of each step, including specific configurations and troubleshooting tips, please refer to the full article mentioned below.
[Creating a Fullstack Web Application with Spring Boot and Next js](https://www.e3docs.com/blog/creating-a-full-stack-web-application-with-spring-boot-and-next-js/)

[Happy coding!](https://medium.com/@h.e3docs/about)😃